package com.ctshk.rpc.train.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.constant.CurrencyIdCode;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.enums.bus.BusConst;
import com.ctshk.common.enums.bus.BusOnShelfStatusCode;
import com.ctshk.common.enums.bus.BusSaleStatusCode;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.service.support.BaseService;
import com.ctshk.common.utils.*;
import com.ctshk.common.utils.individual.conversion.ProductStrategyDateReq;
import com.ctshk.common.utils.individual.conversion.dto.BatchStrategyDto;
import com.ctshk.rpc.order.train.service.ITrainOrderService;
import com.ctshk.rpc.system.dto.MainDataCurrencyQueryDTO;
import com.ctshk.rpc.system.dto.SysAgentQueryListDTO;
import com.ctshk.rpc.system.dto.SysDepartmentDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.req.MainDataCurrencyUpdateStatusReq;
import com.ctshk.rpc.system.req.SysAgentQueryListReq;
import com.ctshk.rpc.system.service.IMainDataCurrencyService;
import com.ctshk.rpc.system.service.ISysAgentService;
import com.ctshk.rpc.system.service.ISysDepartmentService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.train.convertor.Convertor;
import com.ctshk.rpc.train.dto.*;
import com.ctshk.rpc.train.dto.es.ChannelSaleCacheDto;
import com.ctshk.rpc.train.dto.es.ProductChannelOnlineSelfPlatformCacheDto;
import com.ctshk.rpc.train.dto.es.TrainNumberSeatLevelCacheDTO;
import com.ctshk.rpc.train.dto.es.TrainProductCacheDTO;
import com.ctshk.rpc.train.entity.*;
import com.ctshk.rpc.train.enums.SeatAliApiEnum;
import com.ctshk.rpc.train.mapper.*;
import com.ctshk.rpc.train.req.*;
import com.ctshk.rpc.train.service.*;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import com.github.houbb.opencc4j.util.ZhConverterUtil;
import com.google.common.collect.Lists;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 火车产品表 服务实现类
 * </p>
 *
 * @author 彭柳霖
 * @since 2021-03-11
 */
@DubboService
public class TrainProductServiceImpl extends ServiceImpl<TrainProductMapper, TrainProduct> implements ITrainProductService,BaseService {


    @Autowired
    private TrainProductMapper trainProductMapper;
    @Autowired
    private TrainProductCostMapper trainProductCostMapper;
    @Autowired
    private TrainProductCostDateMapper trainProductCostDateMapper;
    @Autowired
    private TrainProducCostPriceMapper trainProducCostPriceMapper;
    @Autowired
    private TrainProductReservationSettingsMapper trainProductReservationSettingsMapper;
    @Autowired
    private TrainProductStrategyMapper trainProductStrategyMapper;
    @Autowired
    private TrainProductIncreaseStrategyRuleMapper ruleMapper;
    @Autowired
    private TrainNumberMapper trainNumberMapper;
    @Autowired
    private TrainProductChannelOfflineSelfCustomMapper trainProductChannelOfflineSelfCustomMapper;
    @Autowired
    private TrainProductChannelOnlineSelfPlatformMapper trainProductChannelOnlineSelfPlatformMapper;
    @Autowired
    private TrainProductChannelOnlineThirdPlatformMapper trainProductChannelOnlineThirdPlatformMapper;
    @Autowired
    private TrainProductChannelOfflineAgentCustomMapper trainProductChannelOfflineAgentCustomMapper;
    @Autowired
    private TrainTicketsInitializationSettingsMapper trainTicketsInitializationSettingsMapper;
    @DubboReference
    private ISysDepartmentService sysDepartmentService;
    @DubboReference
    private ISysAgentService sysAgentService;
    @DubboReference
    ISysUserService sysUserService;
    @DubboReference
    private ITrainApiService iTrainApiService;
    @Autowired
    private TrainStationCodeMapper stationCodeMapper;
    @DubboReference
    private ISysApprovalService iSysApprovalService;
    @DubboReference
    private CJTrainProductService cjTrainProductService;
    @DubboReference
    private ITrainNumberService trainNumberService;

    @DubboReference
    ITrainOrderService trainOrderService;

    @Autowired
    TrainProductStrategyDateMapper trainProductStrategyDateMapper;

    @Autowired
    TrainProductChannelOnlineSelfPlatformMapper platformMapper;

    @Autowired
    TrainNumberSeatLevelMapper trainNumberSeatLevelMapper;

    @Autowired
    TrainStopStationMapper trainStopStationMapper;

    @DubboReference
    ITrainProductStrategyService trainProductStrategyService;

    @DubboReference
    IMainDataCurrencyService mainDataCurrencyService;


    /**
     * 资源中心-分页查询火车票产品列表
     * @param trainProductPageReq
     * @return
     */
    @Override
    public PageResponse<TrainProductPageDTO> queryList(TrainProductPageReq trainProductPageReq) {
        IPage<TrainProduct> iPage = new Page<>(trainProductPageReq.getPageNo(), trainProductPageReq.getPageSize());
        QueryWrapper<TrainProduct> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TrainProduct::getIsDeleted, IsDeletedCode.NO.getCode()).orderByDesc(TrainProduct::getGmtCreate);
        queryWrapper.lambda().and(wrapper -> wrapper.in(TrainProduct::getCreateId, trainProductPageReq.getDataPermissionUserIds()).or()
                .in(TrainProduct::getChargePersonId, trainProductPageReq.getDataPermissionUserIds()));
        //查询条件
        if (!StringUtils.isEmpty(trainProductPageReq.getRailwayCorporationName())) {
            queryWrapper.lambda().like(TrainProduct::getRailwayCorporationName, trainProductPageReq.getRailwayCorporationName());
        }

        if (!StringUtils.isEmpty(trainProductPageReq.getTrainNumberName())) {
            queryWrapper.lambda().eq(TrainProduct::getTrainNumberName, trainProductPageReq.getTrainNumberName());
        }

        if (!StringUtils.isEmpty(trainProductPageReq.getDepartureCityName())) {
            queryWrapper.lambda().like(TrainProduct::getDepartureCityName, trainProductPageReq.getDepartureCityName());
        }

        if (!StringUtils.isEmpty(trainProductPageReq.getArriveCityName())) {
            queryWrapper.lambda().like(TrainProduct::getArriveCityName, trainProductPageReq.getArriveCityName());
        }

        if (!StringUtils.isEmpty(trainProductPageReq.getBoardingStationName())) {
            queryWrapper.lambda().like(TrainProduct::getBoardingStationName, trainProductPageReq.getBoardingStationName());
        }

        if (!StringUtils.isEmpty(trainProductPageReq.getAlightingStationName())) {
            queryWrapper.lambda().like(TrainProduct::getAlightingStationName, trainProductPageReq.getAlightingStationName());
        }

        if (trainProductPageReq.getProductSource()!=null && trainProductPageReq.getProductSource() != 0) {
            queryWrapper.lambda().eq(TrainProduct::getProductSource, trainProductPageReq.getProductSource());
        }

        if (trainProductPageReq.getSaleStatus()!=null && trainProductPageReq.getSaleStatus() != 0) {
            queryWrapper.lambda().eq(TrainProduct::getSaleStatus, trainProductPageReq.getSaleStatus());
        }

        if (trainProductPageReq.getApprovalStatus()!=null && trainProductPageReq.getApprovalStatus() != 0) {
            queryWrapper.lambda().eq(TrainProduct::getApprovalStatus, trainProductPageReq.getApprovalStatus());
        }

        if (trainProductPageReq.getPackStatus()!=null && trainProductPageReq.getPackStatus() != 0) {
            queryWrapper.lambda().eq(TrainProduct::getPackStatus, trainProductPageReq.getPackStatus());
        }

        if (!StringUtils.isEmpty(trainProductPageReq.getSupplierName())) {
            queryWrapper.lambda().like(TrainProduct::getSupplierName, trainProductPageReq.getSupplierName());
        }


        IPage<TrainProduct> trainProductIPage = baseMapper.selectPage(iPage, queryWrapper);

        if (!CollectionUtils.isEmpty(trainProductIPage.getRecords())) {
            List<TrainProductPageDTO> trainProductPageDTOList = EntityUtil.copyList(trainProductIPage.getRecords(), TrainProductPageDTO.class);
            return new PageResponse<>(trainProductPageDTOList, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
        }

        return new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize());
    }

    /**
     * 新增火车票产品信息
     * @param trainProductReq
     * @param user
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result saveTrainProduct(TrainProductReq trainProductReq, TokenUser user) {

        Result checkResult = checkProductReq(trainProductReq,user);
        if(!Objects.isNull(checkResult)){
            return checkResult;
        }

        Result result = checkCostateResult(trainProductReq.getTrainProductCostReqList());
        if(!Objects.isNull(result)){
            return result;
        }
        return this.addProductInfo(trainProductReq,user);
    }

    /**
     * 新增火车产品预订信息
     * @param reservationSettingsReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result saveReservation(TrainProductReservationSettingsReq reservationSettingsReq, TokenUser user) {
        //保存火车票产品预订设置信息
        TrainProductReservationSettings trainProductReservationSettings = EntityUtil.copy(reservationSettingsReq, TrainProductReservationSettings.class);
        trainProductReservationSettings.setId(SnowflakeIdWorker.nextId());
        TrainProduct trainProduct = trainProductMapper.selectById(reservationSettingsReq.getTrainProductId());
        if (Objects.isNull(trainProduct)) {
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14004);
        }
        trainProductReservationSettings.setTicketCollection(JSON.toJSONString(reservationSettingsReq.getTicketCollectionList()));
        trainProductReservationSettingsMapper.insert(trainProductReservationSettings);

        if (reservationSettingsReq.getSaveType() == 1) {
            trainProduct.setApprovalStatus(ApproveCode.UN_COMMIT.getCode());
            trainProductMapper.updateById(trainProduct);
            return Result.success(1);
        } else {
            trainProduct.setApprovalStatus(ApproveCode.APPROVING.getCode());
            Result<ApprovalStartDTO> result = iSysApprovalService.start(SystemBusinessType.TRAIN_TICKET.getCode(),
                    SysApprovalType.ADD_TRAIN.getCode(), trainProduct.getId(), user.getId(), null, null);
            if (result.isSuccess()) {
                trainProduct.setApprovalStatus(ApproveCode.APPROVING.getCode());
                trainProduct.setModifiedId(user.getId());
                trainProduct.setGmtModified(LocalDateTime.now());
                //trainProduct.setTrainNumberId();
                baseMapper.updateById(trainProduct);
                return Result.success(2);
            } else {
                trainProduct.setApprovalStatus(ApproveCode.UN_COMMIT.getCode());
                trainProduct.setModifiedId(user.getId());
                trainProduct.setGmtModified(LocalDateTime.now());
//                trainProduct.setTrainNumberId();
                trainProductMapper.updateById(trainProduct);
                Result failResult = new Result();
                failResult.setCode(result.getCode());
                failResult.setMsg(result.getMsg());
                return failResult;
            }
        }
    }

    /**
     * 修改火车产品预订信息
     * @param reservationSettingsReq
     * @param user
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result updateReservation(TrainProductReservationSettingsReq reservationSettingsReq, TokenUser user) {
        //保存火车票产品预订设置信息
        TrainProductReservationSettings trainProductReservationSettings = EntityUtil.copy(reservationSettingsReq, TrainProductReservationSettings.class);
        TrainProduct trainProduct = trainProductMapper.selectById(reservationSettingsReq.getTrainProductId());
        if(Objects.isNull(trainProduct)){
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14004);
        }
        trainProductReservationSettings.setTicketCollection(JSON.toJSONString(reservationSettingsReq.getTicketCollectionList()));
        trainProductReservationSettingsMapper.updateById(trainProductReservationSettings);
        return Result.success();
    }

    /**
     * 新增-编辑提交审批
     * @param id
     * @param user
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result submit(Long id, TokenUser user) {
        TrainProduct trainProduct = baseMapper.selectById(id);
        if(Objects.isNull(trainProduct)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14004);
        }
        //非待提交状态不能进行审批
        if(!ApproveCode.UN_COMMIT.getCode().equals(trainProduct.getApprovalStatus())){
            return Result.failed(SystemError.TRAIN_PRODUCT_14005);
        }
        // 預訂設置未設置不能進行審批
        TrainProductReservationSettings trainProductReservationSettings = trainProductReservationSettingsMapper.selectOne(
                new QueryWrapper<TrainProductReservationSettings>().lambda().eq(TrainProductReservationSettings::getTrainProductId, trainProduct.getId()));
        if(trainProductReservationSettings == null) {
            return Result.failed(SystemError.TRAIN_PRODUCT_14031);
        }
        Result<ApprovalStartDTO> result = iSysApprovalService.start(SystemBusinessType.TRAIN_TICKET.getCode(),
                SysApprovalType.ADD_TRAIN.getCode(),id,user.getId(),null,null);
        if(result.isSuccess()){
            trainProduct.setApprovalStatus(ApproveCode.APPROVING.getCode());
            trainProduct.setModifiedId(user.getId());
            trainProduct.setGmtModified(LocalDateTime.now());
            baseMapper.updateById(trainProduct);
        } else {
            Result failResult = new Result();
            failResult.setCode(result.getCode());
            failResult.setMsg(result.getMsg());
            return failResult;
        }

        return Result.success(id);
    }


    /**
     * 修改审核通过火车票产品
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result updateApprovedTrainProduct(TrainProductReq trainProductReq, TokenUser user) {


        Result checkResult = checkProductReq(trainProductReq,user);
        if(!Objects.isNull(checkResult)){
            return checkResult;
        }

        Result result = checkCostateResult(trainProductReq.getTrainProductCostReqList());
        if(!Objects.isNull(result)){
            return result;
        }



        //更新火车票产品信息
        TrainProduct trainProduct = baseMapper.selectById(trainProductReq.getId());
        if(Objects.isNull(trainProduct)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14004);
        }
        if(!ApprovalStatus.REVIEW_YES.getCode().equals(trainProduct.getApprovalStatus())){
            return Result.failed(SystemError.TRAIN_PRODUCT_14006);
        }

        if(IsValidCode.VALID.getCode().equals(trainProduct.getSaleStatus())){
            return Result.failed(SystemError.TRAIN_PRODUCT_14007);
        }

        BeanUtils.copyProperties(trainProductReq,trainProduct);
        trainProduct.setModifiedId(user.getId());
        trainProduct.setGmtModified(LocalDateTime.now());
        trainProductMapper.updateById(trainProduct);




        //查询火车票产品成本信息
        List<TrainProductCost> trainProductCostList = trainProductCostMapper.selectList(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId, trainProduct.getId()));

        //更新巴士产品成本相关信息- 先删后插入
        for(TrainProductCost trainProductCost : trainProductCostList){
            trainProductCostDateMapper.delete(new QueryWrapper<TrainProductCostDate>().lambda().eq(TrainProductCostDate::getCostId, trainProductCost.getId()));
            trainProducCostPriceMapper.delete(new QueryWrapper<TrainProducCostPrice>().lambda().eq(TrainProducCostPrice::getCostId, trainProductCost.getId()));
        }
        trainProductCostMapper.delete(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId, trainProduct.getId()));



        //保存火车票产品成本信息
        List<TrainProductCostReq> trainProductCostReqList = trainProductReq.getTrainProductCostReqList();
        for(TrainProductCostReq trainProductCostReq : trainProductCostReqList){
            //保存火车票产品成本
            TrainProductCost trainProductCost = EntityUtil.copy(trainProductCostReq, TrainProductCost.class);
            Long costId = SnowflakeIdWorker.nextId();
            trainProductCost.setId(costId);
            trainProductCost.setTrainProductId(trainProduct.getId());
            trainProductCostMapper.insert(trainProductCost);

            //保存火车票产品成本日期
            List<TrainProductCostDateReq> trainProductCostDateReqList = trainProductCostReq.getTrainProductCostDateReqList();
            for(TrainProductCostDateReq trainProductCostDateReq : trainProductCostDateReqList){
                TrainProductCostDate trainProductCostDate = EntityUtil.copy(trainProductCostDateReq, TrainProductCostDate.class);
                trainProductCostDate.setId(SnowflakeIdWorker.nextId());
                trainProductCostDate.setCostId(costId);
                trainProductCostDateMapper.insert(trainProductCostDate);
            }

            //保存火车票产品成本价格
            List<TrainProducCostPriceReq> trainProducCostPriceReqList = trainProductCostReq.getTrainProducCostPriceReqList();
            for(TrainProducCostPriceReq trainProducCostPriceReq : trainProducCostPriceReqList){
                TrainProducCostPrice trainProducCostPrice = EntityUtil.copy(trainProducCostPriceReq, TrainProducCostPrice.class);
                trainProducCostPrice.setId(SnowflakeIdWorker.nextId());
                trainProducCostPrice.setCostId(costId);
                trainProducCostPriceMapper.insert(trainProducCostPrice);
            }
        }

        return Result.success(trainProduct.getId());
    }

    /**
     * 修改审核不通过火车票产品
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result updateUnapprovedTrainProduct(TrainProductReq trainProductReq, TokenUser user) {

        Result checkResult = checkProductReq(trainProductReq,user);
        if(!Objects.isNull(checkResult)){
            return checkResult;
        }

        Result result = checkCostateResult(trainProductReq.getTrainProductCostReqList());
        if(!Objects.isNull(result)){
            return result;
        }

        TrainProduct trainProduct = trainProductMapper.selectById(trainProductReq.getId());
        if(Objects.isNull(trainProduct)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14004);
        }
        if(!ApprovalStatus.REVIEW_NO.getCode().equals(trainProduct.getApprovalStatus())
        && !ApproveCode.UN_COMMIT.getCode().equals(trainProduct.getApprovalStatus())){
            return Result.failed(SystemError.TRAIN_PRODUCT_14008);
        }

        if(IsValidCode.VALID.getCode().equals(trainProduct.getSaleStatus())){
            return Result.failed(SystemError.TRAIN_PRODUCT_14007);
        }


        //审核不通过修改 等同于新增(必须先删后新增)
        trainProductMapper.deleteById(trainProductReq.getId());

        List<TrainProductCost> trainProductCostList = trainProductCostMapper.
                selectList(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId, trainProductReq.getId()));

        for(TrainProductCost trainProductCost : trainProductCostList){
            trainProductCostDateMapper.delete(new QueryWrapper<TrainProductCostDate>().lambda().eq(TrainProductCostDate::getCostId, trainProductCost.getId()));
            trainProducCostPriceMapper.delete(new QueryWrapper<TrainProducCostPrice>().lambda().eq(TrainProducCostPrice::getCostId, trainProductCost.getId()));
        }
        trainProductCostMapper.delete(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId, trainProductReq.getId()));
        trainProductReservationSettingsMapper.delete(new QueryWrapper<TrainProductReservationSettings>().lambda().eq(TrainProductReservationSettings::getTrainProductId, trainProductReq.getId()));


        //审核不通过的产品 调用新增方法
        return this.addProductInfo(trainProductReq,user);
    }

    /**
     * 查询火车票产品详情信息
     * @param id
     * @return
     */
    @Override
    public TrainProductDTO queryDetail(Long id) {

        TrainProduct trainProduct = trainProductMapper.selectById(id);
        TrainProductDTO trainProductDTO = new TrainProductDTO();
        if (!Objects.isNull(trainProduct)) {
            BeanUtils.copyProperties(trainProduct,trainProductDTO);
        }

        trainProductDTO.setRunningTime(convertRunningTime(trainProductDTO.getDepartureTime(),trainProduct.getTerminusTime()));
        //TrainNumber trainNumber = trainNumberMapper.selectById();
        TrainNumberDTO trainNumberDTO = trainNumberService.queryDetail(trainProduct.getTrainNumberId());
        if(!Objects.isNull(trainNumberDTO)){
            trainProductDTO.setTypeName(trainNumberDTO.getTypeName()); //车次类型名称
            trainProductDTO.setTrainNumberDTO(trainNumberDTO);
        }


        //查询火车票产品成本信息(包括日期和价格)
        List<TrainProductCost> trainProductCostList =  trainProductCostMapper.selectList(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId,id));
        List<TrainProductCostDTO> trainProductCostDTOList = EntityUtil.copyList(trainProductCostList, TrainProductCostDTO.class);

        for(TrainProductCostDTO trainProductCostDTO : trainProductCostDTOList ){
            List<TrainProductCostDate> trainProductCostDateList =  trainProductCostDateMapper.selectList(new QueryWrapper<TrainProductCostDate>().lambda().eq(TrainProductCostDate::getCostId,trainProductCostDTO.getId()));
            List<TrainProducCostPrice> trainProducCostPriceList =  trainProducCostPriceMapper.selectList(new QueryWrapper<TrainProducCostPrice>().lambda().eq(TrainProducCostPrice::getCostId,trainProductCostDTO.getId()));

            List<TrainProductCostDateDTO> trainProductCostDateDTOList = EntityUtil.copyList(trainProductCostDateList, TrainProductCostDateDTO.class);
            List<TrainProductCostPriceDTO> trainProducCostPriceDTOList = EntityUtil.copyList(trainProducCostPriceList, TrainProductCostPriceDTO.class);

            trainProductCostDTO.setTrainProductCostDateDTOList(trainProductCostDateDTOList);
            trainProductCostDTO.setTrainProducCostPriceDTOList(trainProducCostPriceDTOList);
        }
        trainProductDTO.setTrainProductCostDTOList(trainProductCostDTOList);

        //查询火车票产品预订信息
        List<TrainProductReservationSettings> trainProductReservationSettingsList = trainProductReservationSettingsMapper.selectList(new QueryWrapper<TrainProductReservationSettings>().lambda().eq(TrainProductReservationSettings::getTrainProductId,id));
        if(!CollectionUtils.isEmpty(trainProductReservationSettingsList)){
            List<TrainProductReservationSettingsDTO> trainProductReservationSettingsDTOList = EntityUtil.copyList(trainProductReservationSettingsList, TrainProductReservationSettingsDTO.class);
            TrainProductReservationSettingsDTO trainProductReservationSettingsDTO = trainProductReservationSettingsDTOList.get(0);

            trainProductDTO.setTrainProductReservationSettingsDTO(trainProductReservationSettingsDTO);
        }

        return trainProductDTO;
    }

    /**
     * api设置
     * @param trainProductSetReq
     */
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Result setApi(TrainProductSetReq trainProductSetReq, TokenUser user) {

        TrainProduct trainProduct = trainProductMapper.selectById(trainProductSetReq.getId());
        if(Objects.isNull(trainProduct)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14004);
        }
        //是API产品才可以设置
        if(ProductType.API_PRODUCT.getCode().equals(trainProduct.getProductSource())){
            trainProduct.setPackStatus(trainProductSetReq.getPackStatus());
            trainProduct.setRefundFeeType(trainProductSetReq.getRefundFeeType());
            trainProduct.setRefundFeePrice(trainProductSetReq.getRefundFeePrice());
            trainProduct.setServiceChargeType(trainProductSetReq.getServiceChargeType());
            trainProduct.setServiceChargePrice(trainProductSetReq.getServiceChargePrice());
            trainProduct.setModifiedId(user.getId());
            trainProduct.setGmtModified(LocalDateTime.now());
            trainProductMapper.updateById(trainProduct);
        }else{
            return Result.failed(SystemError.TRAIN_PRODUCT_14009);
        }
        return Result.success();
    }


    /**
     * 有效无效设置
     * @param id
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result setValid(Long id, TokenUser user) {

        TrainProduct trainProduct = trainProductMapper.selectById(id);
        if(Objects.isNull(trainProduct)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14004);
        }
        //只有API产品 或已审批的人工录入产品才能设置有效
        if(ProductType.API_PRODUCT.getCode().equals(trainProduct.getProductSource()) ||
                (ProductType.MANUAL_ENTRY.getCode().equals(trainProduct.getProductSource()) && ApprovalStatus.REVIEW_YES.getCode().equals(trainProduct.getApprovalStatus()))){

            if(IsValidCode.VALID.getCode().equals(trainProduct.getSaleStatus())){
                trainProduct.setSaleStatus(IsValidCode.IN_VALID.getCode()); //设置为无效
            }else{
                trainProduct.setSaleStatus(IsValidCode.VALID.getCode()); //设置为有效
            }
            trainProduct.setModifiedId(user.getId());
            trainProduct.setGmtModified(LocalDateTime.now());
            trainProductMapper.updateById(trainProduct);
        }else{
            return Result.failed(SystemError.TRAIN_PRODUCT_14010);
        }
        return Result.success();
    }

    /**
     * 批量设置
     * @param batchTrainProductInfoReq
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public Result batchSetting(BatchTrainProductInfoReq batchTrainProductInfoReq, TokenUser user) {


        List<TrainProduct> busProductList = trainProductMapper.selectList(new QueryWrapper<TrainProduct>().lambda().in(TrainProduct::getId, batchTrainProductInfoReq.getTrainProductIds()));

        //判断产品来源是否相同
        if(!CollectionUtils.isEmpty(busProductList)){
            for(TrainProduct trainProduct : busProductList){
                if(!busProductList.get(0).getProductSource().equals(trainProduct.getProductSource())){
                    return Result.failed(SystemError.TRAIN_PRODUCT_14011);
                }
                if(ProductType.MANUAL_ENTRY.getCode().equals(trainProduct.getProductSource()) &&
                        !ApprovalStatus.REVIEW_YES.getCode().equals(trainProduct.getApprovalStatus())){
                    return Result.failed(SystemError.TRAIN_PRODUCT_14012);
                }
            }
            for(TrainProduct trainProduct: busProductList){
                trainProduct.setPackStatus(batchTrainProductInfoReq.getPackStatus());
                trainProduct.setSaleStatus(batchTrainProductInfoReq.getSaleStatus());
                trainProduct.setModifiedId(user.getId());
                trainProduct.setGmtModified(LocalDateTime.now());
                trainProductMapper.updateById(trainProduct);
            }
        }

        return Result.success();
    }

    @Override
    public Result setRecommended(Long id, TokenUser user) {
        TrainProduct trainProduct = trainProductMapper.selectById(id);
        if(Objects.isNull(trainProduct)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14002);
        }
        if(Constants.RECOMMENDED.equals(trainProduct.getRecommendationStatus())){
            trainProduct.setRecommendationStatus(Constants.UN_RECOMMENDED); //设置为不推荐
        }else{
            trainProduct.setRecommendationStatus(Constants.RECOMMENDED); //设置为推荐
        }
        trainProduct.setModifiedId(user.getId());
        trainProduct.setGmtModified(LocalDateTime.now());
        trainProductMapper.updateById(trainProduct);
        return Result.success();
    }

    /**
     * 查询巴士票推荐列表
     */
    @Override
    public List<RecommendedTrainDTO> queryRecommendedBusTicket(Long userId, RecommendedBusTicketReq req) {
        LocalDate nowDate = LocalDate.now();
        List<RecommendedTrainDTO> recommendedTrainDTOList = trainProductMapper.queryRecommendedTrainTicket(req);
        if(CollectionUtils.isEmpty(recommendedTrainDTOList)) {
            return null;
        }
        for (RecommendedTrainDTO recommendedTrainDTO : recommendedTrainDTOList) {
            TrainProductIncreaseStrategyRule trainProductIncreaseStrategyRule = null;
            // 获取成本价
            BigDecimal costPrice = recommendedTrainDTO.getPrice();
            // 查询火车票-当前日期加幅策略
            TrainProductStrategyDTO trainProductStrategyDTO = trainProductStrategyMapper.queryTrainProductStrategyInfo(recommendedTrainDTO.getTrainProductId(), nowDate);
            if (trainProductStrategyDTO != null) {
                if (trainProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                    // 自营禁售
                    continue;
                } else if (trainProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                    //火车票-线下自营所有-获取加幅规则
                    trainProductIncreaseStrategyRule = ruleMapper.selectById(trainProductStrategyDTO.getSelfSalePermissionId());
                } else if (trainProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    //火车票-线下自营选中-获取加幅规则
                    QueryWrapper<TrainProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
                    offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getRelationId, userId);
                    offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getIncreaseStrategyId, trainProductStrategyDTO.getId());
                    TrainProductChannelOfflineSelfCustom trainProductChannelOfflineSelfCustom = trainProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
                    if (trainProductChannelOfflineSelfCustom != null) {
                        // 火车票-线下自营选中-查询加幅规则
                        QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, trainProductChannelOfflineSelfCustom.getId());
                        trainProductIncreaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                    } else {
                        SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryByUserId(userId);
                        trainProductChannelOfflineSelfCustom = findParentDepartmentId(sysDepartmentDTO, trainProductStrategyDTO.getId());
                        if (trainProductChannelOfflineSelfCustom != null) {
                            // 火车票-线下自营选中-查询加幅规则
                            QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                            ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, trainProductChannelOfflineSelfCustom.getId());
                            trainProductIncreaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                        }
                    }
                }
            }

            if (trainProductIncreaseStrategyRule != null) {
                // 火车票-手工录入产品上架加幅规则
                if(!Constants.API.equals(recommendedTrainDTO.getProductSource())){
                    buildIncreasePrice(recommendedTrainDTO,
                            trainProductIncreaseStrategyRule.getPriceType(),trainProductIncreaseStrategyRule.getPrice());
                }
            }
            //预订设置信息
            List<TrainProductReservationSettings> reservationSettingsList = trainProductReservationSettingsMapper.selectList(new QueryWrapper<TrainProductReservationSettings>().lambda()
                    .eq(TrainProductReservationSettings::getTrainProductId, recommendedTrainDTO.getTrainProductId()));
            TrainProductReservationSettings reservationSettings = Assist.findFirst(reservationSettingsList);
            if (reservationSettings != null) {
                // recommendedTrainDTO.setIsConfirm(reservationSettings.getIsConfirm());
                // recommendedTrainDTO.setBookingInformation(reservationSettings.getBookingInformation());
                // recommendedTrainDTO.setChangeSettings(reservationSettings.getChangeSettings());
                Integer serviceChargeType = reservationSettings.getServiceChargeType();
                BigDecimal serviceChargePrice = reservationSettings.getServiceChargePrice();
                // 设置成本价+加幅价+服务费
                if(serviceChargeType == 1) {
                    // 加数值
                    if(costPrice != null) {
                        recommendedTrainDTO.setPrice(recommendedTrainDTO.getPrice().add(serviceChargePrice));
                    }
                } else if(serviceChargeType == 2) {
                    // 加百分比
                    BigDecimal per = serviceChargePrice.divide(new BigDecimal("100"));
                    if(costPrice != null) {
                        BigDecimal multiply = costPrice.multiply(per);
                        recommendedTrainDTO.setPrice(recommendedTrainDTO.getPrice().add(multiply));
                    }
                }
            }
        }

        return recommendedTrainDTOList;
    }

    /**
     * 预订中心-分页查询巴士票
     * @param req
     * @return
     */
    @Override
    public PageResponse<ReservationTrainPageDTO> queryReservationBusList(ReservationTrainPageReq req, Long userId) {
        // 港铁直通车查询
        if (req.getRailwayTypeCode() == 1) {
            // 获取站点Code
            TrainStationCode startStationCode = stationCodeMapper.selectOne(new QueryWrapper<TrainStationCode>().lambda().eq(TrainStationCode::getStationCh, req.getBoardingStationName()).eq(TrainStationCode::getStationSimple, "GZ"));
            TrainStationCode endStationCode = stationCodeMapper.selectOne(new QueryWrapper<TrainStationCode>().lambda().eq(TrainStationCode::getStationCh, req.getAlightingStationName()).eq(TrainStationCode::getStationSimple, "GZ"));
            if (Objects.isNull(startStationCode) || Objects.isNull(endStationCode)) {
                log.error("火车站点三字码不存在 上车站:"+ req.getBoardingStationName()+",下车站:" + req.getAlightingStationName());
                return null;
            }
            List<ReservationTrainPageDTO> list = cjTrainProductService.getTrainNumberList(startStationCode.getStationEn(), endStationCode.getStationEn(),
                    req.getBoardingStationName(), req.getAlightingStationName(),
                    req.getQueryDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            IPage<ReservationTrainPageDTO> agentPage = new Page<>(req.getPageNo(),req.getPageSize());
            agentPage.setRecords(list);
            return new PageResponse<>(agentPage.getRecords(),agentPage.getCurrent() == 1,
                    agentPage.getTotal() <= (agentPage.getCurrent() * agentPage.getSize()),
                    agentPage.getTotal(), agentPage.getCurrent(), agentPage.getSize());
        }

        //拼接余位条件
        req.setInventory(req.getPassengerAdultNum() + req.getPassengerChildrenNum() + req.getPassengerOldNum());
        if (req.getQueryDate() == null) {
            req.setQueryDate(LocalDate.now());
        }
        // 设置明日日期
        //req.setTomorrowQueryDate(req.getQueryDate().plusDays(1));
        req.setPageSize(Integer.MAX_VALUE);
        IPage<ReservationTrainPageDTO> agentPage = new Page<>(req.getPageNo(),req.getPageSize());
        agentPage = trainProductMapper.queryReservationBusList(req,agentPage);

        List<ReservationTrainPageDTO> reservationTrainPageDTOList = agentPage.getRecords();
        if(CollectionUtils.isEmpty(reservationTrainPageDTOList)){
            agentPage.setRecords(Lists.newArrayList());
            //return null;
        }
        //LocalDate nowDate = LocalDate.now();
        List<ReservationTrainPageDTO> filterList = new ArrayList<>();
        Map<String,ReservationTrainPageDTO> trainNumberProductMap = new HashMap<>();
        for(ReservationTrainPageDTO busPageDTO : reservationTrainPageDTOList){
            // 过滤不符合的创建人和负责人
            if(!userId.equals(busPageDTO.getChargePersonId()) && !userId.equals(busPageDTO.getCreateId())) {
                continue;
            }
            TrainProductIncreaseStrategyRule trainProductIncreaseStrategyRule = null;
            // 查询巴士-当前日期加幅策略
            TrainProductStrategyDTO trainProductStrategyDTO = trainProductStrategyMapper.queryTrainProductStrategyInfo(busPageDTO.getTrainProductId(), req.getQueryDate());
            if (trainProductStrategyDTO != null) {
                if (trainProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                    // 自营禁售
                    continue;
                } else if (trainProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                    //巴士-线下自营所有-获取加幅规则
                    trainProductIncreaseStrategyRule = ruleMapper.selectById(trainProductStrategyDTO.getSelfSalePermissionId());
                    // 取成本中心每日可售数,加幅策略可售数中的最小值做余票
                    // 加幅策略为空则跳过
                    if(trainProductIncreaseStrategyRule == null) {
                        continue;
                    }
                    trainProductIncreaseStrategyRule.setStock(busPageDTO.getStock());
                    busPageDTO.setTicketNum(buildRemainderNumber(trainProductIncreaseStrategyRule));
                } else if (trainProductStrategyDTO.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    //巴士-线下自营选中-获取加幅规则
                    QueryWrapper<TrainProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
                    offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getRelationId, userId);
                    offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getIncreaseStrategyId, trainProductStrategyDTO.getId());
                    TrainProductChannelOfflineSelfCustom busProductChannelOfflineSelfCustom = trainProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
                    if (busProductChannelOfflineSelfCustom != null) {
                        // 巴士-线下自营选中-查询加幅规则
                        QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineSelfCustom.getId());
                        trainProductIncreaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                        // 加幅策略为空则跳过
                        if(trainProductIncreaseStrategyRule == null) {
                            continue;
                        }
                        trainProductIncreaseStrategyRule.setStock(busPageDTO.getStock());
                        busPageDTO.setTicketNum(buildRemainderNumber(trainProductIncreaseStrategyRule));
                    } else {
                        SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryByUserId(userId);
                        busProductChannelOfflineSelfCustom = findParentDepartmentId(sysDepartmentDTO, trainProductStrategyDTO.getId());
                        if (busProductChannelOfflineSelfCustom != null) {
                            // 巴士-线下自营选中-查询加幅规则
                            QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                            ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineSelfCustom.getId());
                            trainProductIncreaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                            // 加幅策略为空则跳过
                            if(trainProductIncreaseStrategyRule == null) {
                                continue;
                            }
                            trainProductIncreaseStrategyRule.setStock(busPageDTO.getStock());
                            busPageDTO.setTicketNum(buildRemainderNumber(trainProductIncreaseStrategyRule));
                        }
                    }
                }
                // 判断代理商权限类型
                if (trainProductStrategyDTO.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED
                || trainProductStrategyDTO.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    busPageDTO.setIsShowAgent(true);
                }

            }
            List<TrainProducCostPrice> priceList = trainProducCostPriceMapper.selectList(new QueryWrapper<TrainProducCostPrice>().lambda().eq(TrainProducCostPrice::getCostId,busPageDTO.getCostId()));
            if(!CollectionUtils.isEmpty(priceList)){
                for(TrainProducCostPrice price : priceList){
                    if(price.getPassengerId() == 1){
                        busPageDTO.setAdultPrice(price.getPrice());
                    }else if(price.getPassengerId() == 2){
                        busPageDTO.setChildrenPrice(price.getPrice());
                    }
                }
                if(req.getPassengerAdultNum() > 0 && busPageDTO.getAdultPrice() == null) {
                    continue;
                }
                if(req.getPassengerChildrenNum() > 0 && busPageDTO.getChildrenPrice() == null) {
                    continue;
                }
            }
            // 成人小童成本价
            BigDecimal adultCostPrice = busPageDTO.getAdultPrice();
            BigDecimal childrenCostPrice = busPageDTO.getChildrenPrice();

            if (trainProductIncreaseStrategyRule != null) {
                if(!Constants.API.equals(busPageDTO.getProductSource())) {
                    // 火车非API产品根据上架加幅规则价幅
                    addeAdultPrice(busPageDTO,
                            trainProductIncreaseStrategyRule.getPriceType(),trainProductIncreaseStrategyRule.getPrice());
                    addeChildRenPrice(busPageDTO,
                            trainProductIncreaseStrategyRule.getPriceType(),trainProductIncreaseStrategyRule.getPrice());
                }
            }
            //预订设置信息
            List<TrainProductReservationSettings> reservationSettingsList = trainProductReservationSettingsMapper.selectList(new QueryWrapper<TrainProductReservationSettings>().lambda()
                    .eq(TrainProductReservationSettings::getTrainProductId, busPageDTO.getTrainProductId()));
            TrainProductReservationSettings reservationSettings = Assist.findFirst(reservationSettingsList);
            if (reservationSettings != null) {
                busPageDTO.setIsConfirm(reservationSettings.getIsConfirm());
                busPageDTO.setBookingInformation(reservationSettings.getBookingInformation());
                busPageDTO.setChangeSettings(reservationSettings.getChangeSettings());
                Integer serviceChargeType = reservationSettings.getServiceChargeType();
                BigDecimal serviceChargePrice = reservationSettings.getServiceChargePrice() == null?BigDecimal.ZERO:reservationSettings.getServiceChargePrice();
                BigDecimal adultPrice = busPageDTO.getAdultPrice();
                BigDecimal childrenPrice = busPageDTO.getChildrenPrice();
                // 设置成本价+加幅价
                busPageDTO.setAdultPrimePrice(adultPrice);
                busPageDTO.setChildrenPrimePrice(childrenPrice);
                if(serviceChargeType == 1) {
                    // 加数值
                    if(adultPrice != null) {
                        busPageDTO.setAdultServiceChargePrice(serviceChargePrice);
                        busPageDTO.setAdultPrice(adultPrice.add(serviceChargePrice));
                    }
                    if(childrenPrice != null) {
                        busPageDTO.setChildrenServiceChargePrice(serviceChargePrice);
                        busPageDTO.setChildrenPrice(childrenPrice.add(serviceChargePrice));
                    }
                } else if(serviceChargeType == 2) {
                    BigDecimal per = serviceChargePrice.divide(new BigDecimal("100"));
                    // 加百分比
                    if(adultCostPrice != null) {
                        BigDecimal multiply = adultCostPrice.multiply(per);
                        busPageDTO.setAdultServiceChargePrice(multiply);
                        busPageDTO.setAdultPrice(adultPrice.add(multiply));
                    }
                    if(childrenCostPrice != null) {
                        BigDecimal multiply = childrenCostPrice.multiply(per);
                        busPageDTO.setChildrenServiceChargePrice(multiply);
                        busPageDTO.setChildrenPrice(childrenPrice.add(multiply));
                    }
                }
            }

            busPageDTO.setRunningTime(convertRunningTime(busPageDTO.getDepartureTime(),busPageDTO.getTerminusTime()));

            //聚合同車次,同出發站,同到達站的產品
            //車次id
            Long trainNumberId = busPageDTO.getTrainNumberId();
            //上車站Id
            Long boardingStationId = busPageDTO.getBoardingStationId();
            //下車站Id
            Long alightingStationId = busPageDTO.getAlightingStationId();
            StringBuffer sb = new StringBuffer();
            sb.append(trainNumberId);
            sb.append(boardingStationId);
            sb.append(alightingStationId);
            String key = sb.toString();
            ReservationTrainPageDTO trainNumberReservationTrainPageDTO = trainNumberProductMap.get(key);
            if(trainNumberReservationTrainPageDTO != null) {
                ReservationTrainSeatInfoDTO copy = EntityUtil.copy(busPageDTO, ReservationTrainSeatInfoDTO.class);
                // 设置最低价
                BigDecimal copyMin = getMinPrice(copy.getAdultPrice(),copy.getChildrenPrice());
                BigDecimal min = getMinPrice(trainNumberReservationTrainPageDTO.getMinPrice(),copyMin);
                trainNumberReservationTrainPageDTO.setMinPrice(min);
                copy.setTicketNum(String.valueOf(busPageDTO.getTicketNum()));
                trainNumberReservationTrainPageDTO.getReservationTrainSeatInfoDTOList().add(copy);
            } else {
                ReservationTrainPageDTO reservationTrainPageDTO = EntityUtil.copy(busPageDTO,ReservationTrainPageDTO.class);
                List<ReservationTrainSeatInfoDTO> reservationTrainSeatInfoDTOList = new ArrayList<>();
                ReservationTrainSeatInfoDTO copy = EntityUtil.copy(busPageDTO, ReservationTrainSeatInfoDTO.class);
                // 设置最低价
                BigDecimal copyMin = getMinPrice(copy.getAdultPrice(),copy.getChildrenPrice());
                reservationTrainPageDTO.setMinPrice(copyMin);
                copy.setTicketNum(String.valueOf(busPageDTO.getTicketNum()));

                reservationTrainSeatInfoDTOList.add(copy);
                reservationTrainPageDTO.setReservationTrainSeatInfoDTOList(reservationTrainSeatInfoDTOList);
                trainNumberProductMap.put(key,reservationTrainPageDTO);
                filterList.add(reservationTrainPageDTO);
            }
        }
        agentPage.setRecords(filterList);
        try {
            // 获取阿里云api产品信息
            List<ReservationTrainPageDTO> aliList = buildAliTrainList(req);
            agentPage.getRecords().addAll(aliList);
        } catch (Exception e) {
            log.error("api查询火车票异常",e);
        }

        PageResponse<ReservationTrainPageDTO> result = new PageResponse<>(agentPage.getRecords(),agentPage.getCurrent() == 1,
                agentPage.getTotal() <= (agentPage.getCurrent() * agentPage.getSize()),
                agentPage.getTotal(), agentPage.getCurrent(), agentPage.getSize());
        return result;
    }

    /**
     *
     * @param d1 出发时间
     * @param d2 到达时间
     * @return
     */
    private String convertRunningTime(LocalDateTime d1,LocalDateTime d2) {
        if(d1 == null || d2 == null) {
            return null;
        }
        long minutes = Duration.between(d1, d2).toMinutes();
        long minute = minutes % 60L;
        long hour = minutes / 60L;
        return hour + "小时" + minute + "分";
    }

    /**
     * 获取最低价,为null的忽略
     * @param price1
     * @param price2
     * @return
     */
    private BigDecimal getMinPrice(BigDecimal price1, BigDecimal price2) {
        if(price1 == null) {
            return price2;
        }
        if(price2 == null) {
            return price1;
        }
        return NumberUtil.min(price1,price2);
    }


    private List<ReservationTrainPageDTO> buildAliTrainList(ReservationTrainPageReq req) {
        // 获取汇率
        MainDataCurrencyQueryDTO exchangeRate = getExchangeRateByCurrencyId(CurrencyIdCode.CNY.getCode());
        List<ReservationTrainPageDTO> reservationTrainPageDTOS = new ArrayList<>();
        TrainTicketQueryReq queryReq = new TrainTicketQueryReq();
        queryReq.setDate(req.getQueryDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        queryReq.setStart(ZhConverterUtil.toSimple(req.getBoardingStationName()));
        queryReq.setEnd(ZhConverterUtil.toSimple(req.getAlightingStationName()));
        List<ApiTrainProductDTO> list = null;
        try {
            list = iTrainApiService.getTrainTicketList(queryReq);
        } catch (Exception e) {
            e.printStackTrace();
        }
        list.stream().filter(trainStation -> {
            // 过滤不符合的出发站,到达站
            return trainStation.getStation().equals(ZhConverterUtil.toSimple(req.getBoardingStationName()))
                    && trainStation.getEndstation().equals(ZhConverterUtil.toSimple(req.getAlightingStationName()));
        }).forEach(trainStation -> {
            // 封装返回参数
            ReservationTrainPageDTO trainPageDTO = new ReservationTrainPageDTO();
            trainPageDTO.setDepartureTime(LocalTime.parse(trainStation.getDeparturetime(),DateTimeFormatter.ofPattern("HH:mm")).atDate(req.getQueryDate()));
            trainPageDTO.setTerminusTime(LocalTime.parse(trainStation.getArrivaltime(),DateTimeFormatter.ofPattern("HH:mm")).atDate(req.getQueryDate()));

            trainPageDTO.setRunningTime(trainStation.getCosttime());
            trainPageDTO.setSupplierName("阿里云api");
            trainPageDTO.setTrainNumberName(trainStation.getTrainno());
            Long id = SnowflakeIdWorker.nextId();
            trainPageDTO.setTrainProductId(id);
            trainPageDTO.setProductSource(Constants.ALI);
            trainPageDTO.setBoardingStationName(req.getBoardingStationName());
            trainPageDTO.setAlightingStationName(req.getAlightingStationName());
            if(trainPageDTO.getReservationTrainSeatInfoDTOList() == null) {
                trainPageDTO.setReservationTrainSeatInfoDTOList(new ArrayList<>());
            }
            // 拆分座席
            List<ApiTrainProductSeatInfoDTO> seatlist = devideApiTrainProductToSeatInfo(trainStation);
            final BigDecimal[] minPrice = {BigDecimal.ZERO};
            seatlist.forEach(seatInfo -> {
                // 人民币转港币
                BigDecimal price = (seatInfo.getPrice().multiply(exchangeRate.getCrmExchangeRate())).setScale(2, BigDecimal.ROUND_HALF_UP);
                price = roundPrice(price);
                if (minPrice[0].equals(BigDecimal.ZERO)) {
                    minPrice[0] = price;
                }
                if (price.compareTo(minPrice[0]) < 0) {
                    minPrice[0] = price;
                }
                ReservationTrainSeatInfoDTO reservationTrainSeatInfoDTO = new ReservationTrainSeatInfoDTO();
                reservationTrainSeatInfoDTO.setAdultPrice(price);
                reservationTrainSeatInfoDTO.setSeatLevelName(seatInfo.getSeatLevelName());
                reservationTrainSeatInfoDTO.setSupplierName("阿里云api");
                reservationTrainSeatInfoDTO.setTicketNum(seatInfo.getNum());
                trainPageDTO.getReservationTrainSeatInfoDTOList().add(reservationTrainSeatInfoDTO);
            });

            trainPageDTO.setMinPrice(minPrice[0]);
            reservationTrainPageDTOS.add(trainPageDTO);
        });
        return reservationTrainPageDTOS;
    }

    /**
     * 【【火車票】阿里雲，價格小數2位小於0.5向上補0.5，大於0.5向上補1塊】
     * https://www.tapd.cn/42567854/bugtrace/bugs/view/1142567854001006212
     * @param b
     * @return
     */
    private BigDecimal roundPrice(BigDecimal b) {
        BigDecimal fractionalPart = b.remainder(BigDecimal.ONE);
        if (fractionalPart.compareTo(new BigDecimal("0.5")) < 0) {
            b = b.setScale(0, BigDecimal.ROUND_DOWN).add(new BigDecimal("0.5"));
        } else if (fractionalPart.compareTo(new BigDecimal("0.5")) > 0) {
            b = b.setScale(0, BigDecimal.ROUND_DOWN).add(new BigDecimal("1"));
        }
        return b;
    }

    /**
     * 根据币种ID获取汇率，获取汇率,
     *
     * @return
     */
    private MainDataCurrencyQueryDTO getExchangeRateByCurrencyId(Long currencyId) {
        MainDataCurrencyUpdateStatusReq mainDataCurrencyUpdateStatusReq = new MainDataCurrencyUpdateStatusReq();
        mainDataCurrencyUpdateStatusReq.setId(currencyId);
        Result<MainDataCurrencyQueryDTO> queryCurrencyRateResult = mainDataCurrencyService.query(mainDataCurrencyUpdateStatusReq);
        if (!queryCurrencyRateResult.isSuccess()) {
            SystemError defined = SystemError.getDefined(queryCurrencyRateResult.getCode());
            throw new BusinessException(defined);
        }
        return queryCurrencyRateResult.getData();
    }

    /**
     * 拆分座席数据
     * @param apiTrainProductDTO
     * @return
     */
    private List<ApiTrainProductSeatInfoDTO> devideApiTrainProductToSeatInfo(ApiTrainProductDTO apiTrainProductDTO) {
        List<ApiTrainProductSeatInfoDTO> list = new ArrayList<>();
        try {
            Class<? extends ApiTrainProductDTO> aClass = apiTrainProductDTO.getClass();
            Method[] methods = aClass.getDeclaredMethods();
            for (Method method : methods) {
                String methodName = method.getName();
                if(methodName.startsWith("getPrice")) {
                    String suffix = methodName.substring(methodName.indexOf("getPrice") + 8);
                    String price = (String) method.invoke(apiTrainProductDTO);
                    // 查询票价,如果为"-"代表没有该座次
                    if("-".equals(price)) {
                        continue;
                    }
                    ApiTrainProductSeatInfoDTO apiTrainProductSeatInfoDTO = new ApiTrainProductSeatInfoDTO();
                    apiTrainProductSeatInfoDTO.setPrice(new BigDecimal(price));
                    String seatLevelName = SeatAliApiEnum.getName(suffix);
                    apiTrainProductSeatInfoDTO.setSeatLevelName(seatLevelName);
                    // 有票价查询余票数
                    Method declaredMethod = aClass.getDeclaredMethod("getNum" + suffix);
                    String num = (String) declaredMethod.invoke(apiTrainProductDTO);
                    apiTrainProductSeatInfoDTO.setNum(num);
                    list.add(apiTrainProductSeatInfoDTO);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return list;
    }

    /**
     * 根据火车票产品id和用户id，查询用户自营下的加幅后价格和余票信息,售出数量增加
     *
     * @param trainProductId
     * @param touristNumber
     * @param userId
     * @param effectiveDate
     * @return
     */
    @Override
    public TrainPriceRemainderDTO selectSelfPriceRemainderAndLock(Long trainProductId, int touristNumber, Long userId, LocalDate effectiveDate) {
        TrainPriceRemainderDTO trainPriceRemainderDTO = new TrainPriceRemainderDTO();
        TrainProductIncreaseStrategyRule strategyRule = null;
        Integer remainderNumber = null;
        TrainProduct trainProduct = trainProductMapper.selectById(trainProductId);
        TrainProductStrategyDTO trainProductStrategy = trainProductStrategyMapper.queryTrainProductStrategyInfo(trainProductId, effectiveDate);
        if (trainProductStrategy != null) {
            // 代理禁售
            if (trainProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                return null;
            } else if (trainProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                //当前巴士-线下自营所有-获取加幅规则
                strategyRule = ruleMapper.selectById(trainProductStrategy.getSelfSalePermissionId());

            } else if (trainProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                //当前巴士-线下自营选中-获取加幅规则
                QueryWrapper<TrainProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
                offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getRelationId, userId);
                offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getIncreaseStrategyId, trainProductStrategy.getId());
                TrainProductChannelOfflineSelfCustom offlineSelfCustom = trainProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
                if (offlineSelfCustom != null) {
                    // 当前机场快线-线下自营选中-查询加幅规则
                    QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                    ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, offlineSelfCustom.getId());
                    strategyRule = ruleMapper.selectOne(ruleQueryWrapper);

                } else {
                    SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryByUserId(userId);
                    offlineSelfCustom = findParentDepartmentId(sysDepartmentDTO, trainProductStrategy.getId());
                    if (offlineSelfCustom != null) {
                        // 当前机场快线-线下自营选中-查询加幅规则
                        QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, offlineSelfCustom.getId());
                        strategyRule = ruleMapper.selectOne(ruleQueryWrapper);

                    }
                }
            }
        }

        //查询产品成本价
        BigDecimal primeAdultPrice = BigDecimal.ZERO;
        BigDecimal primeChildPrice = BigDecimal.ZERO;
        List<TrainProductCostPriceDTO> priceDTOList = trainProductCostMapper.queryPrice(trainProduct.getId(),effectiveDate);
        if(!CollectionUtils.isEmpty(priceDTOList)){
            for(TrainProductCostPriceDTO priceDTO : priceDTOList){
                if(priceDTO.getPassengerId() == 1){
                    primeAdultPrice = priceDTO.getPrice();
                }else if(priceDTO.getPassengerId() == 2){
                    primeChildPrice = priceDTO.getPrice();
                }
            }
        }

        //设置成本价格
        trainPriceRemainderDTO.setAdultPrimePrice(primeAdultPrice);
        trainPriceRemainderDTO.setChildrenPrimePrice(primeChildPrice);

        // 巴士-加幅规则失效后，按照初始化设置查询加幅规则
        if (strategyRule != null) {
            if (strategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT) {
                // 票数有限制，计算余票数量
                int saleableNumber = strategyRule.getSaleableNumber() == null ? 0 : strategyRule.getSaleableNumber();
                int soldNumber = strategyRule.getSoldNumber() == null ? 0 : strategyRule.getSoldNumber();
                remainderNumber = saleableNumber - soldNumber;
                if (touristNumber > remainderNumber) {
                    // 旅客人数大于余票数量
                    throw new BusinessException(SystemError.AIREXPRESS_ORDER_60000);
                }
                // 锁定票数 AtomicIncreaseSoldNumber
                TrainProductIncreaseStrategyRule updateStrategyRule = new TrainProductIncreaseStrategyRule();
                updateStrategyRule.setId(strategyRule.getId());
                updateStrategyRule.setSoldNumber(soldNumber + touristNumber);
                ruleMapper.updateById(updateStrategyRule);
            }

            Integer adultPriceType = strategyRule.getPriceType();
            BigDecimal adultPrice = strategyRule.getPrice();

            Integer childPriceType = strategyRule.getPriceType();
            BigDecimal childPrice = strategyRule.getPrice();



            if(adultPriceType == 1){ //加数值
                primeAdultPrice = primeAdultPrice.add(adultPrice);
            }else if(adultPriceType == 2){
                //加百分比
                BigDecimal per = adultPrice.divide(new BigDecimal("100"));
                primeAdultPrice = primeAdultPrice.add(primeAdultPrice.multiply(per));
            }

            if(childPriceType == 1){ //加数值
                primeChildPrice = primeChildPrice.add(childPrice);
            }else if(childPriceType == 2){
                //加百分比
                BigDecimal per = childPrice.divide(new BigDecimal("100"));
                primeChildPrice = primeChildPrice.add(primeChildPrice.multiply(per));
            }
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(strategyRule.getSaleableType());
            trainPriceRemainderDTO.setRemainderNumber(remainderNumber);
        }else{
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(Constants.SALE_TYPE_UNLIMITED);
        }
        return trainPriceRemainderDTO;
    }

    /**
     * 根据火车票产品id和用户id，查询用户代理下的加幅后价格和余票信息,售出数量增加
     *
     * @param busProductId
     * @param touristNumber
     * @param userId
     * @param effectiveDate
     * @return
     */
    @Override
    public TrainPriceRemainderDTO selectAgentPriceRemainderAndLock(Long busProductId, int touristNumber, Long agentId, Long userId, LocalDate effectiveDate) {
        TrainPriceRemainderDTO trainPriceRemainderDTO = new TrainPriceRemainderDTO();
        TrainProductIncreaseStrategyRule strategyRule = null;
        Integer remainderNumber = null;
        TrainProduct trainProduct = trainProductMapper.selectById(busProductId);
        if (Objects.isNull(trainProduct)) {
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14004);
        }

        // 查询巴士-当前日期加幅策略
        TrainProductStrategyDTO busProductStrategy = trainProductStrategyMapper.queryTrainProductStrategyInfo(busProductId, effectiveDate);
        if (busProductStrategy != null) {
            // 代理禁售
            if (busProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                return null;
            } else if (busProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                // 当前机场快线-线下自营所有-获取加幅规则
                strategyRule = ruleMapper.selectById(busProductStrategy.getAgentSalePermissionId());

            } else if (busProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                //当前机场快线-线下代理选中-获取代理加幅规则列表
                QueryWrapper<TrainProductChannelOfflineAgentCustom> offlineAgentQueryWrapper = new QueryWrapper<>();
                offlineAgentQueryWrapper.lambda().eq(TrainProductChannelOfflineAgentCustom::getIncreaseStrategyId, busProductStrategy.getId());
                offlineAgentQueryWrapper.lambda().eq(TrainProductChannelOfflineAgentCustom::getAgentId, agentId);
                TrainProductChannelOfflineAgentCustom offlineAgentCustom = trainProductChannelOfflineAgentCustomMapper.selectOne(offlineAgentQueryWrapper);
                if (offlineAgentCustom != null) {
                    // 当前机场快线-线下代理选中-查询加幅规则
                    QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                    ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, offlineAgentCustom.getId());
                    strategyRule = ruleMapper.selectOne(ruleQueryWrapper);

                }
            }
        }
        BigDecimal primeAdultPrice = BigDecimal.ZERO;
        BigDecimal primeChildPrice = BigDecimal.ZERO;

        List<TrainProductCostPriceDTO> priceDTOList = trainProductCostMapper.queryPrice(trainProduct.getId(),effectiveDate);

        if(!CollectionUtils.isEmpty(priceDTOList)){
            for(TrainProductCostPriceDTO priceDTO : priceDTOList){
                if(priceDTO.getPassengerId() == 1){
                    primeAdultPrice = priceDTO.getPrice();
                }else if(priceDTO.getPassengerId() == 2){
                    primeChildPrice = priceDTO.getPrice();
                }
            }
        }

        //设置成本价格
        trainPriceRemainderDTO.setAdultPrimePrice(primeAdultPrice);
        trainPriceRemainderDTO.setChildrenPrimePrice(primeChildPrice);

        // 机场快线-产品代理加幅规则没有数据时，使用初始化设置全部代理
        if (strategyRule != null) {
            if (strategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT) {
                // 票数有限制，计算余票数量
                int saleableNumber = strategyRule.getSaleableNumber() == null ? 0 : strategyRule.getSaleableNumber();
                int soldNumber = strategyRule.getSoldNumber() == null ? 0 : strategyRule.getSoldNumber();
                remainderNumber = saleableNumber - soldNumber;
                // 锁定票数 AtomicIncreaseSoldNumber
                TrainProductIncreaseStrategyRule updateStrategyRule = new TrainProductIncreaseStrategyRule();
                updateStrategyRule.setId(strategyRule.getId());
                updateStrategyRule.setSoldNumber(strategyRule.getSoldNumber() + touristNumber);
                ruleMapper.updateById(updateStrategyRule);
            }

            Integer adultPriceType = strategyRule.getPriceType();
            BigDecimal adultPrice = strategyRule.getPrice();

            Integer childPriceType = strategyRule.getPriceType();
            BigDecimal childPrice = strategyRule.getPrice();



            if(adultPriceType == 1){ //加数值
                primeAdultPrice = primeAdultPrice.add(adultPrice);
            }else if(adultPriceType == 2){
                //加百分比
                primeAdultPrice = primeAdultPrice.add(primeAdultPrice.multiply(adultPrice));
            }

            if(childPriceType == 1){ //加数值
                primeChildPrice = primeChildPrice.add(childPrice);
            }else if(childPriceType == 2){
                //加百分比
                primeChildPrice = primeChildPrice.add(primeChildPrice.multiply(childPrice));
            }
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(strategyRule.getSaleableType());
            trainPriceRemainderDTO.setRemainderNumber(remainderNumber);
        }else{
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(Constants.SALE_TYPE_UNLIMITED);
        }
        return trainPriceRemainderDTO;
    }

    @Override
    public List<TrainTouristTypeDTO> queryTouristType() {
        List<TrainTouristTypeDTO> trainTouristTypeDTOList = Lists.newArrayList();
        for (TrainTouristType value : TrainTouristType.values()) {
            TrainTouristTypeDTO touristTypeDTO = new TrainTouristTypeDTO();
            touristTypeDTO.setTouristType(value.getType());
            touristTypeDTO.setTouristTypeName(value.getName());
            trainTouristTypeDTOList.add(touristTypeDTO);

        }
        return trainTouristTypeDTOList;
    }

    @Override
    public Result<PageResponse<TrainProductDTO>> queryProductListForIotc(TrainProductListForIotcQueryReq req) {
        QueryWrapper<TrainProduct> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(Assist.isNotBlank(req.getProductCode()), TrainProduct::getProductCode, req.getProductCode());
        queryWrapper.lambda().eq(Assist.isNotBlank(req.getSupplierId()), TrainProduct::getSupplierId, req.getSupplierId());
        queryWrapper.lambda().eq(Assist.isNotBlank(req.getDepartureCityId()), TrainProduct::getDepartureCityId, req.getDepartureCityId());
        queryWrapper.lambda().eq(Assist.isNotBlank(req.getArriveCityId()), TrainProduct::getArriveCityId, req.getArriveCityId());
        queryWrapper.lambda().eq(Assist.isNotBlank(req.getSeatLevelId()), TrainProduct::getSeatLevelId, req.getSeatLevelId());
        queryWrapper.lambda().like(Assist.isNotBlank(req.getRailwayCorporationName()), TrainProduct::getRailwayCorporationName, req.getRailwayCorporationName());
        queryWrapper.lambda().like(Assist.isNotBlank(req.getTrainNumberName()), TrainProduct::getTrainNumberName, req.getTrainNumberName());
        IPage<TrainProductDTO> iPage = trainProductMapper.selectPage(TrainProductDTO.class, req, queryWrapper);
        if (CollectionUtils.isEmpty(iPage.getRecords())) {
            return Result.success(new PageResponse<>(new ArrayList<>(), iPage.getCurrent() == 1,
                    iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize()));
        }
        return Result.success(new PageResponse<>(iPage.getRecords(),
                iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize()));
    }

    @Override
    public Result<List<TrainProductDTO>> queryProductListByIdForIotc(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            return Result.success(new ArrayList<>());
        }
        List<TrainProductDTO> list = trainProductMapper.selectBatchIds(TrainProductDTO.class, idList);
        if (CollectionUtils.isEmpty(list)) {
            return Result.success(new ArrayList<>());
        }
        return Result.success(list);
    }

    @Override
    public Result<Long> check(TrainProductCheckReq trainProductCheckReq, TokenUser currentUser) {
        Result<ApprovalCheckDTO> result = iSysApprovalService.check(trainProductCheckReq.getId(),currentUser.getId(),trainProductCheckReq.getStatus(),trainProductCheckReq.getReason());
        if(result.isSuccess()){
            if(result.getData().getIsFinish()){
                TrainProduct trainProduct = baseMapper.selectById(trainProductCheckReq.getProductId());
                trainProduct.setModifiedId(currentUser.getId());
                trainProduct.setGmtModified(LocalDateTime.now());
                if(trainProductCheckReq.getStatus() == ApprovalStatus.REVIEW_YES.getCode()){
                    // 审批通过
                    trainProduct.setSaleStatus(IsValidCode.VALID.getCode());
                }
                trainProduct.setApprovalStatus(trainProductCheckReq.getStatus());
                baseMapper.updateById(trainProduct);
            }
        }else {
            Result result1 = new Result();
            result1.setCode(result.getCode());
            result1.setMsg(result.getMsg());
            return result1;
        }
        return Result.success(trainProductCheckReq.getId());
    }

    @Override
    public Result<List<TrainProductReservationAgentDTO>> queryReservationAgentList(TrainProductReservationAgentQueryReq req, TokenUser currentUser) {

        TrainProduct trainProduct = trainProductMapper.assertExistById(req.getId());
        TrainProductStrategyDTO trainProductStrategy = trainProductStrategyMapper.queryTrainProductStrategyInfo(trainProduct.getId(), req.getQueryDate());
        if (trainProductStrategy == null) {
            throw new BusinessException(SystemError.TRAIN_PRODUCT_14032);
        }

        //销售渠道类型：禁售
        if (trainProductStrategy.getAgentSalePermissionType() == null || Constants.SALE_CHANNEL_TYPE_DISABLED.equals(trainProductStrategy.getAgentSalePermissionType())) {
            return newResult();
        }

        //成本价
        Map<Long, BigDecimal> costPriceMap = trainProductCostMapper.queryPriceMap(trainProduct.getId(), req.getQueryDate());

        List<TrainProductReservationAgentDTO> list = new ArrayList<>();
        //加幅规则
        TrainProductIncreaseStrategyRule increaseStrategyRule = null;
        //获取所有有效代理商
        List<SysAgentQueryListDTO> agentDtoList = getSysBigClientQueryListDTOS();

        if (Constants.SALE_CHANNEL_TYPE_ALL.equals(trainProductStrategy.getAgentSalePermissionType())) {  //销售渠道类型：所有
            //加幅规则
            increaseStrategyRule = ruleMapper.selectById(trainProductStrategy.getAgentSalePermissionId());

            if (Assist.isNotEmpty(agentDtoList)) {
                for (SysAgentQueryListDTO agentDto : agentDtoList) {
                    TrainProductReservationAgentDTO dto = new TrainProductReservationAgentDTO();
                    dto.setId(agentDto.getId());
                    dto.setAgentName(agentDto.getGroupCnName());
                    //封装代理价格
                    packReservationAgentPrice(dto, costPriceMap, increaseStrategyRule);
                    list.add(dto);;
                }
            }
        } else if (Constants.SALE_CHANNEL_TYPE_SELECTED.equals(trainProductStrategy.getAgentSalePermissionType())) {  //销售渠道类型：选中的
            List<TrainProductChannelOfflineAgentCustom> agentCustomList = trainProductChannelOfflineAgentCustomMapper.selectList(
                    new QueryWrapper<TrainProductChannelOfflineAgentCustom>().lambda().eq(TrainProductChannelOfflineAgentCustom::getIncreaseStrategyId, trainProductStrategy.getId())
            );
            if (Assist.isNotEmpty(agentCustomList)) {
                for (TrainProductChannelOfflineAgentCustom agentCustom : agentCustomList) {
                    //加幅规则
                    increaseStrategyRule = ruleMapper.selectById(agentCustom.getId());

                    TrainProductReservationAgentDTO dto = new TrainProductReservationAgentDTO();
                    dto.setId(agentCustom.getAgentId());
                    dto.setAgentName(agentCustom.getAgentName());
                    //封装代理价格
                    packReservationAgentPrice(dto, costPriceMap, increaseStrategyRule);
                    list.add(dto);
                }
            }
        }

        return newResult(list);
    }

    @Override
    public List<TrainProductCacheDTO> queryTrainProductList(List<String> trainNumberNames) {
        if(trainNumberNames == null || trainNumberNames.size() <= 0){
            return null;
        }

        // 获取产品列表
        LambdaQueryWrapper<TrainProduct> productWrapper = Wrappers.<TrainProduct>lambdaQuery().eq(TrainProduct::getIsDeleted, IsDeletedCode.NO.getCode());
        productWrapper.eq(TrainProduct::getSaleStatus, BusSaleStatusCode.VALID.getCode());
        productWrapper.eq(TrainProduct::getApprovalStatus, ApprovalStatus.REVIEW_YES.getCode());
        productWrapper.eq(TrainProduct::getOnShelfStatus, BusOnShelfStatusCode.UP_SHELF.getCode());
//         测试用，先写死
//        productWrapper.eq(TrainProduct::getTrainNumberName,"ZGGT519");
////        // TODO 正式版使用这个条件
        productWrapper.in(TrainProduct::getTrainNumberName,trainNumberNames);
        List<TrainProduct> trainProducts = baseMapper.selectList(productWrapper);
        Map<Long, TrainProduct> trainProductMap = trainProducts.stream().collect(Collectors.toMap(TrainProduct::getId, Function.identity(), (key1, key2) -> key2));
        List<TrainProductCacheDTO> trainProductDTOS = EntityUtil.copyList(trainProducts, TrainProductCacheDTO.class);
        List<TrainProductCacheDTO> newTrainProductDTOS = new ArrayList<>();

        // 获取产品预订设置
        List<TrainProductReservationSettings> settingsList = trainProductReservationSettingsMapper.selectList(new QueryWrapper<TrainProductReservationSettings>().lambda()
                .in(TrainProductReservationSettings::getTrainProductId, new ArrayList<>(trainProductMap.keySet())));
        Map<Long, TrainProductReservationSettings> settingMap = settingsList.stream().collect(Collectors.toMap(TrainProductReservationSettings::getTrainProductId, Function.identity(), (key1, key2) -> key2));

        // 补充产品其余信息
        Map<String,TrainProductCacheDTO> trainProductCacheMap = new HashMap<>();
        trainProductDTOS.forEach(product -> {
            // 获取产品加辐有效期
            List<TrainProductStrategyDTO> list = trainProductStrategyService.queryByProductId(product.getId());
            BatchStrategyDto batchStrategyDto = Convertor.TrainProductToFront(list);
            List<ChannelSaleCacheDto> channelSaleCacheList = new ArrayList<>();
            if (batchStrategyDto == null) {
                return;
            }
            batchStrategyDto.getStrategyList().forEach(strategyDto -> {
                if (CollectionUtils.isEmpty(strategyDto.getChannelSaleReq().getProductChannelOnlineSelfPlatformReqList())) {
                    return;
                }
                List<ProductStrategyDateReq> dateReqs = strategyDto.getTime();
                for (ProductStrategyDateReq dateReq : dateReqs) {
                    ChannelSaleCacheDto saleCacheDto = new ChannelSaleCacheDto();
                    saleCacheDto.setProductChannelOnlineSelfPlatformCacheList(EntityUtil.copyList(strategyDto.getChannelSaleReq().getProductChannelOnlineSelfPlatformReqList(), ProductChannelOnlineSelfPlatformCacheDto.class));
                    saleCacheDto.setDateBegin(dateReq.getDateBegin());
                    saleCacheDto.setDateEnd(dateReq.getDateEnd());
                    channelSaleCacheList.add(saleCacheDto);
                }
            });
            if (CollectionUtils.isEmpty(channelSaleCacheList)) {
                return;
            }
            product.setChannelSaleCacheList(channelSaleCacheList);

            // 巴士产品最近7天销量
            Integer count = trainOrderService.findBusProduct7DaySaleCount(product.getId());
            product.setSaleCount(count == null ? 0 : count);

            // 产品加幅策略
            TrainPriceRemainderDTO remainderDTO = this.selectAppPriceRemainder(product.getId(),
                    LocalDate.now(), ChannelMainData.APP_H5);

            TrainPriceRemainderDTO remainderPcDTO = this.selectAppPriceRemainder(product.getId(),
                    LocalDate.now(), ChannelMainData.CHINA_TRAVEL);

            // 没有加辐策略跳过
            if (remainderDTO == null && remainderPcDTO == null) {
                return;
            }

            //聚合同車次,同出發站,同到達站的產品
            //車次id
            String trainNumberId = product.getTrainNumberName();
            //上車站Id
            Long boardingStationId = product.getBoardingStationId();
            //下車站Id
            Long alightingStationId = product.getAlightingStationId();
            StringBuffer sb = new StringBuffer();
            sb.append(trainNumberId);
            sb.append(boardingStationId);
            sb.append(alightingStationId);
            String key = sb.toString();
            TrainProductCacheDTO trainProductCacheDTO = trainProductCacheMap.get(key);
            if(trainProductCacheDTO != null) {
                TrainNumberSeatLevelCacheDTO copy = EntityUtil.copy(product, TrainNumberSeatLevelCacheDTO.class);
                trainProductCacheDTO.getTrainNumberSeatLevelCacheDTOS().add(copy);
                product.setTrainNumberSeatLevelCacheDTOS(trainProductCacheDTO.getTrainNumberSeatLevelCacheDTOS());
            } else {
                List<TrainNumberSeatLevelCacheDTO> trainNumberSeatLevelCacheDTOS = new ArrayList<>();
                TrainNumberSeatLevelCacheDTO copy = EntityUtil.copy(product, TrainNumberSeatLevelCacheDTO.class);
                TrainProduct trainProduct = trainProductMap.get(copy.getId());
                copy.setServiceChargeType(trainProduct.getServiceChargeType());
                copy.setServiceChargePrice(trainProduct.getServiceChargePrice());
                copy.setSeatNumber(String.valueOf(remainderDTO.getRemainderNumber()));
                trainNumberSeatLevelCacheDTOS.add(copy);
                product.setTrainNumberSeatLevelCacheDTOS(trainNumberSeatLevelCacheDTOS);
                trainProductCacheMap.put(key,product);
            }

            // 设置价格
            product.getTrainNumberSeatLevelCacheDTOS().forEach(seatLevel->{
                TrainProductReservationSettings reservationSettings = settingMap.get(seatLevel.getId());
                if (reservationSettings != null) {
                    seatLevel.setBookingInformation(reservationSettings.getBookingInformation());
                    seatLevel.setPassengerNotice(reservationSettings.getPassengerNotice());
                    seatLevel.setChildrenNotice(reservationSettings.getChildrenNotice());
                    seatLevel.setElectronicTicketExplain(reservationSettings.getElectronicTicketExplain());
                }
                if (remainderPcDTO != null) {
                    seatLevel.setPcPrice(remainderPcDTO.getAdultPrice());
                    seatLevel.setPcChildPrice(remainderPcDTO.getChildrenPrice());
                }
                if (remainderDTO != null) {
                    seatLevel.setH5Price(remainderDTO.getAdultPrice());
                    seatLevel.setH5ChildPrice(remainderDTO.getChildrenPrice());
                }
            });
            newTrainProductDTOS.add(product);
        });
        return newTrainProductDTOS;
    }

    private TrainPriceRemainderDTO selectAppPriceRemainder(Long trainProductId, LocalDate effectiveDate, ChannelMainData mainData) {
        TrainPriceRemainderDTO trainPriceRemainderDTO = new TrainPriceRemainderDTO();
        TrainProductIncreaseStrategyRule strategyRule = null;
        Integer remainderNumber = null;
        TrainProduct trainProduct = trainProductMapper.selectById(trainProductId);
        TrainProductStrategyDTO trainProductStrategy = trainProductStrategyMapper.queryTrainProductStrategyInfo(trainProductId, effectiveDate);
        if (trainProductStrategy != null) {
            QueryWrapper<TrainProductChannelOnlineSelfPlatform> onlineSelfPlatformQueryWrapper = new QueryWrapper<>();
            onlineSelfPlatformQueryWrapper.lambda().eq(TrainProductChannelOnlineSelfPlatform::getIncreaseStrategyId, trainProductStrategy.getId());
            onlineSelfPlatformQueryWrapper.lambda().eq(TrainProductChannelOnlineSelfPlatform::getChannelId, mainData.getId());
            TrainProductChannelOnlineSelfPlatform trainProductChannelOfflineSelfCustom = trainProductChannelOnlineSelfPlatformMapper.selectOne(onlineSelfPlatformQueryWrapper);
            if (trainProductChannelOfflineSelfCustom == null) {
                return null;
            }
            // 火车票-线上自营-查询加幅规则
            QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
            ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, trainProductChannelOfflineSelfCustom.getId());
            strategyRule = ruleMapper.selectOne(ruleQueryWrapper);
        }

        //查询产品成本价
        BigDecimal primeAdultPrice = BigDecimal.ZERO;
        BigDecimal primeChildPrice = BigDecimal.ZERO;
        List<TrainProductCostPriceDTO> priceDTOList = trainProductCostMapper.queryPrice(trainProduct.getId(),effectiveDate);
        if(!CollectionUtils.isEmpty(priceDTOList)){
            for(TrainProductCostPriceDTO priceDTO : priceDTOList){
                if(priceDTO.getPassengerId() == 1){
                    primeAdultPrice = priceDTO.getPrice();
                }else if(priceDTO.getPassengerId() == 2){
                    primeChildPrice = priceDTO.getPrice();
                }
            }
        }

        //设置成本价格
        trainPriceRemainderDTO.setAdultPrimePrice(primeAdultPrice);
        trainPriceRemainderDTO.setChildrenPrimePrice(primeChildPrice);

        // 火车-加幅规则失效后，按照初始化设置查询加幅规则
        if (strategyRule != null) {
            if (strategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT) {
                // 票数有限制，计算余票数量
                int saleableNumber = strategyRule.getSaleableNumber() == null ? 0 : strategyRule.getSaleableNumber();
                int soldNumber = strategyRule.getSoldNumber() == null ? 0 : strategyRule.getSoldNumber();
                remainderNumber = saleableNumber - soldNumber;
            } else {
                remainderNumber = -1;
            }
            Integer adultPriceType = strategyRule.getPriceType();
            BigDecimal adultPrice = strategyRule.getPrice();
            Integer childPriceType = strategyRule.getPriceType();
            BigDecimal childPrice = strategyRule.getPrice();

            if(adultPriceType == 1){ //加数值
                primeAdultPrice = primeAdultPrice.add(adultPrice);
            }else if(adultPriceType == 2){
                //加百分比
                BigDecimal per = adultPrice.divide(new BigDecimal("100"));
                primeAdultPrice = primeAdultPrice.add(primeAdultPrice.multiply(per));
            }
            if(childPriceType == 1){ //加数值
                primeChildPrice = primeChildPrice.add(childPrice);
            }else if(childPriceType == 2){
                //加百分比
                BigDecimal per = childPrice.divide(new BigDecimal("100"));
                primeChildPrice = primeChildPrice.add(primeChildPrice.multiply(per));
            }
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(strategyRule.getSaleableType());
            trainPriceRemainderDTO.setRemainderNumber(remainderNumber);
        }else{
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(Constants.SALE_TYPE_UNLIMITED);
            trainPriceRemainderDTO.setRemainderNumber(-1);
        }
        return trainPriceRemainderDTO;
    }

    @Override
    public TrainPriceRemainderDTO selectAppPriceRemainderAndLock(Long trainProductId, int touristNumber, LocalDate effectiveDate, ChannelMainData mainData) {
        TrainPriceRemainderDTO trainPriceRemainderDTO = new TrainPriceRemainderDTO();
        TrainProductIncreaseStrategyRule strategyRule = null;
        Integer remainderNumber = null;
        TrainProduct trainProduct = trainProductMapper.selectById(trainProductId);
        TrainProductStrategyDTO trainProductStrategy = trainProductStrategyMapper.queryTrainProductStrategyInfo(trainProductId, effectiveDate);
        if (trainProductStrategy != null) {
            QueryWrapper<TrainProductChannelOnlineSelfPlatform> onlineSelfPlatformQueryWrapper = new QueryWrapper<>();
            onlineSelfPlatformQueryWrapper.lambda().eq(TrainProductChannelOnlineSelfPlatform::getIncreaseStrategyId, trainProductStrategy.getId());
            onlineSelfPlatformQueryWrapper.lambda().eq(TrainProductChannelOnlineSelfPlatform::getChannelId, mainData.getId());
            TrainProductChannelOnlineSelfPlatform trainProductChannelOfflineSelfCustom = trainProductChannelOnlineSelfPlatformMapper.selectOne(onlineSelfPlatformQueryWrapper);
            if (trainProductChannelOfflineSelfCustom == null) {
                return null;
            }
            // 火车票-线上自营-查询加幅规则
            QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
            ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, trainProductChannelOfflineSelfCustom.getId());
            strategyRule = ruleMapper.selectOne(ruleQueryWrapper);
        }

        //查询产品成本价
        BigDecimal primeAdultPrice = BigDecimal.ZERO;
        BigDecimal primeChildPrice = BigDecimal.ZERO;
        List<TrainProductCostPriceDTO> priceDTOList = trainProductCostMapper.queryPrice(trainProduct.getId(),effectiveDate);
        if(!CollectionUtils.isEmpty(priceDTOList)){
            for(TrainProductCostPriceDTO priceDTO : priceDTOList){
                if(priceDTO.getPassengerId() == 1){
                    primeAdultPrice = priceDTO.getPrice();
                }else if(priceDTO.getPassengerId() == 2){
                    primeChildPrice = priceDTO.getPrice();
                }
            }
        }

        //设置成本价格
        trainPriceRemainderDTO.setAdultPrimePrice(primeAdultPrice);
        trainPriceRemainderDTO.setChildrenPrimePrice(primeChildPrice);

        // 巴士-加幅规则失效后，按照初始化设置查询加幅规则
        if (strategyRule != null) {
            if (strategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT) {
                // 票数有限制，计算余票数量
                int saleableNumber = strategyRule.getSaleableNumber() == null ? 0 : strategyRule.getSaleableNumber();
                int soldNumber = strategyRule.getSoldNumber() == null ? 0 : strategyRule.getSoldNumber();
                remainderNumber = saleableNumber - soldNumber;
                if (touristNumber > remainderNumber) {
                    // 旅客人数大于余票数量
                    throw new BusinessException(SystemError.AIREXPRESS_ORDER_60000);
                }
                // 锁定票数 AtomicIncreaseSoldNumber
                TrainProductIncreaseStrategyRule updateStrategyRule = new TrainProductIncreaseStrategyRule();
                updateStrategyRule.setId(strategyRule.getId());
                updateStrategyRule.setSoldNumber(soldNumber + touristNumber);
                ruleMapper.updateById(updateStrategyRule);
            }

            Integer adultPriceType = strategyRule.getPriceType();
            BigDecimal adultPrice = strategyRule.getPrice();

            Integer childPriceType = strategyRule.getPriceType();
            BigDecimal childPrice = strategyRule.getPrice();



            if(adultPriceType == 1){ //加数值
                primeAdultPrice = primeAdultPrice.add(adultPrice);
            }else if(adultPriceType == 2){
                //加百分比
                BigDecimal per = adultPrice.divide(new BigDecimal("100"));
                primeAdultPrice = primeAdultPrice.add(primeAdultPrice.multiply(per));
            }

            if(childPriceType == 1){ //加数值
                primeChildPrice = primeChildPrice.add(childPrice);
            }else if(childPriceType == 2){
                //加百分比
                BigDecimal per = childPrice.divide(new BigDecimal("100"));
                primeChildPrice = primeChildPrice.add(primeChildPrice.multiply(per));
            }
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(strategyRule.getSaleableType());
            trainPriceRemainderDTO.setRemainderNumber(remainderNumber);
        }else{
            trainPriceRemainderDTO.setAdultPrice(primeAdultPrice);
            trainPriceRemainderDTO.setChildrenPrice(primeChildPrice);
            trainPriceRemainderDTO.setSaleableType(Constants.SALE_TYPE_UNLIMITED);
        }
        return trainPriceRemainderDTO;
    }

    @Override
    public TrainPriceRemainderDTO findTrainSalePriceInfoHandle(int strategyType, Long productId, LocalDate departureDate, Long relId) {
        validateNotNull(strategyType, productId, departureDate, relId);

        TrainPriceRemainderDTO trainPriceRemainderDTO = new TrainPriceRemainderDTO();
        //库存数
        int saleableNumber = -1;
        TrainProduct trainProduct = trainProductMapper.assertExistById(productId);
        TrainProductStrategy trainProductStrategy = trainProductStrategyMapper.findTrainProductStrategy(trainProduct.getId(), departureDate);

        trainPriceRemainderDTO.setId(trainProduct.getId());
//        trainPriceRemainderDTO.setDepartureDate(departureDate);
//        trainPriceRemainderDTO.setIsLimitTicket(BConst.ONE);
//        trainPriceRemainderDTO.setSaleableNumber(0);
        trainPriceRemainderDTO.setRemainderNumber(0);
//        trainPriceRemainderDTO.setProductSource(trainProduct.getProductSource());

        // 获取加幅策略规则
        TrainProductIncreaseStrategyRule increaseStrategyRule = findTrainSalePriceInfoByStrategyRule(strategyType, relId, trainProductStrategy);

        //预订设置信息
        TrainProductReservationSettings reservationSettings = trainProductReservationSettingsMapper.selectOneByKey("train_product_id", trainProduct.getId());


        List<TrainProductCostPriceDTO> priceDTOList = trainProductCostMapper.queryPrice(trainProduct.getId(), LocalDate.now());
        //成本价格map，key：旅客类型；value：成本价
        Map<Long, BigDecimal> costPriceMap = Assist.forEachToMap(priceDTOList, TrainProductCostPriceDTO::getPassengerId, TrainProductCostPriceDTO::getPrice);
        //成人成本价
        BigDecimal adultCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_ADULT);
        trainPriceRemainderDTO.setAdultPrimePrice(adultCostPrice);
        //小童成本价
        BigDecimal childrenCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_CHILD);
        trainPriceRemainderDTO.setChildrenPrimePrice(childrenCostPrice);

        if (Assist.isNotEmpty(priceDTOList)) {
            TrainProductCostPriceDTO costPriceDto = Assist.findFirst(priceDTOList);
            if (costPriceDto != null && costPriceDto.getCostId() != null) {
                TrainProductCost busProductCost = trainProductCostMapper.assertExistById(costPriceDto.getCostId());
                notNull(busProductCost.getCurrencyId(), SystemError.AIREXPRESS_ORDER_60029);

                //非HKD转换汇率
                if (!BusConst.CURRENCY_ID_HKD.equals(busProductCost.getCurrencyId())) {
                    BigDecimal rate = mainDataCurrencyService.getPlanneRateById(busProductCost.getCurrencyId());
                    notNull(rate, SystemError.AIREXPRESS_ORDER_60029);
                    adultCostPrice = Assist.calcRateTwo(adultCostPrice, rate);
                    childrenCostPrice = Assist.calcRateTwo(childrenCostPrice, rate);
                }
            }
        }

        trainPriceRemainderDTO.setAdultPrice(adultCostPrice);
        trainPriceRemainderDTO.setChildrenPrice(childrenCostPrice);

        //非API产品
        //服务费加幅
        if (reservationSettings != null) {
            trainPriceRemainderDTO.setAdultPrice(addeServicePrice(reservationSettings, adultCostPrice, trainPriceRemainderDTO.getAdultPrice()));
            trainPriceRemainderDTO.setChildrenPrice(addeServicePrice(reservationSettings, childrenCostPrice, trainPriceRemainderDTO.getChildrenPrice()));
        }

        //加幅
        if (increaseStrategyRule != null) {
            //有限制销售数量
            if (increaseStrategyRule.getSaleableType() == Constants.SALE_TYPE_LIMIT) {
                // 票数有限制，计算余票数量
                saleableNumber = increaseStrategyRule.getSaleableNumber() == null ? 0 : increaseStrategyRule.getSaleableNumber();
            }

            //价格加幅
            trainPriceRemainderDTO.setAdultPrice(addePrice(increaseStrategyRule, adultCostPrice, trainPriceRemainderDTO.getAdultPrice()));
            trainPriceRemainderDTO.setChildrenPrice(addePrice(increaseStrategyRule, childrenCostPrice, trainPriceRemainderDTO.getChildrenPrice()));

            //计算余票数
            int remainderNumber = calcRemainderNum(saleableNumber, trainProduct.getId(), departureDate);
            trainPriceRemainderDTO.setRemainderNumber(remainderNumber);
        }
        return trainPriceRemainderDTO;

    }

    /**
     * 计算余票数
     */
    private int calcRemainderNum(int saleableNumber, Long busProductId, LocalDate queryDate) {
//        //巴士产品已售信息
//        BusProductSold entity = busProductSoldMapper.selectOneByKey("bus_product", busProductId, "sale_date", queryDate);
//        if (entity != null && entity.getSoldNumber() != null) {
//            saleableNumber -= entity.getSoldNumber();
//        }
        return saleableNumber;
    }

    /**
     * 价格服务费加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addeServicePrice(TrainProductReservationSettings rule, BigDecimal costPrice, BigDecimal price) {
        if (price == null)
            return null;
        return price.add(addeServicePrice(rule, costPrice));
    }

    /**
     * 价格服务费加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addeServicePrice(TrainProductReservationSettings rule, BigDecimal costPrice) {
        if (rule == null)
            return BigDecimal.ZERO;
        return addePrice(rule.getServiceChargeType(), rule.getServiceChargePrice(), costPrice);
    }

    /**
     * 查询巴士产品售价信息,加幅规则
     * @param strategyType 加幅类型，1：自营；2：代理；3：官方平台；4：第三方平台；
     * @param relId 关联ID，strategyType(1：用户ID；2：代理ID；3：渠道ID；4：渠道ID)
     * @return
     */
    private TrainProductIncreaseStrategyRule findTrainSalePriceInfoByStrategyRule(int strategyType, Long relId, TrainProductStrategy trainProductStrategy) {
        TrainProductIncreaseStrategyRule increaseStrategyRule = null;
        if (trainProductStrategy != null) {
            //自营
            if (strategyType == 1) {
                if (trainProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                    // 代理禁售
                } else if (trainProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                    //当前机场快线-线下自营所有-获取加幅规则
                    increaseStrategyRule = ruleMapper.selectById(trainProductStrategy.getSelfSalePermissionId());
                } else if (trainProductStrategy.getSelfSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    //当前机场快线-线下自营选中-获取加幅规则
                    QueryWrapper<TrainProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
                    offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getRelationId, relId);
                    offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getIncreaseStrategyId, trainProductStrategy.getId());
                    TrainProductChannelOfflineSelfCustom busProductChannelOfflineSelfCustom = trainProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
                    if (busProductChannelOfflineSelfCustom != null) {
                        // 当前机场快线-线下自营选中-查询加幅规则
                        QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineSelfCustom.getId());
                        increaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);

                    } else {
                        SysDepartmentDTO sysDepartmentDTO = sysDepartmentService.queryByUserId(relId);
                        busProductChannelOfflineSelfCustom = findParentDepartmentId(sysDepartmentDTO, trainProductStrategy.getId());
                        if (busProductChannelOfflineSelfCustom != null) {
                            // 当前机场快线-线下自营选中-查询加幅规则
                            QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                            ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineSelfCustom.getId());
                            increaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                        }
                    }
                }
            } else if (strategyType == 2) {  //代理
                // 代理禁售
                if (trainProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_DISABLED) {
                } else if (trainProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_ALL) {
                    // 当前机场快线-线下自营所有-获取加幅规则
                    increaseStrategyRule = ruleMapper.selectById(trainProductStrategy.getAgentSalePermissionId());
                } else if (trainProductStrategy.getAgentSalePermissionType() == Constants.SALE_CHANNEL_TYPE_SELECTED) {
                    //当前机场快线-线下代理选中-获取代理加幅规则列表
                    QueryWrapper<TrainProductChannelOfflineAgentCustom> offlineAgentQueryWrapper = new QueryWrapper<>();
                    offlineAgentQueryWrapper.lambda().eq(TrainProductChannelOfflineAgentCustom::getIncreaseStrategyId, trainProductStrategy.getId());
                    offlineAgentQueryWrapper.lambda().eq(TrainProductChannelOfflineAgentCustom::getAgentId, relId);
                    TrainProductChannelOfflineAgentCustom busProductChannelOfflineAgentCustom = trainProductChannelOfflineAgentCustomMapper.selectOne(offlineAgentQueryWrapper);
                    if (busProductChannelOfflineAgentCustom != null) {
                        // 当前机场快线-线下代理选中-查询加幅规则
                        QueryWrapper<TrainProductIncreaseStrategyRule> ruleQueryWrapper = new QueryWrapper<>();
                        ruleQueryWrapper.lambda().eq(TrainProductIncreaseStrategyRule::getCustomId, busProductChannelOfflineAgentCustom.getId());
                        increaseStrategyRule = ruleMapper.selectOne(ruleQueryWrapper);
                    }
                }
            } else if (strategyType == 3) {  //官方平台
                TrainProductChannelOnlineSelfPlatform onlineSelfPlatform = trainProductChannelOnlineSelfPlatformMapper.selectOneByKey("increase_strategy_id", trainProductStrategy.getId(), "channel_id", relId);
                if (onlineSelfPlatform != null) {
                    increaseStrategyRule = ruleMapper.selectOneByKey("custom_id", onlineSelfPlatform.getId());
                }
            } else if (strategyType == 4) {  //第三方平台

            }
        }
        return increaseStrategyRule;
    }

    /**
     * 查询系统有效代理商列表
     *
     * @return
     */
    private List<SysAgentQueryListDTO> getSysBigClientQueryListDTOS() {
        SysAgentQueryListReq sysBigClientQueryListReq = new SysAgentQueryListReq();
        sysBigClientQueryListReq.setPageNo(1);
        sysBigClientQueryListReq.setPageSize(1000);
        sysBigClientQueryListReq.setStatus(1);
        PageResponse<SysAgentQueryListDTO> sysBigClientQueryListDTOPageResponse = sysAgentService.queryAgentListAll(sysBigClientQueryListReq);
        return sysBigClientQueryListDTOPageResponse.getRecords();
    }

    /**
     * 封装代理价格
     * @param dto
     */
    private void packReservationAgentPrice(TrainProductReservationAgentDTO dto, Map<Long, BigDecimal> costPriceMap, TrainProductIncreaseStrategyRule increaseStrategyRule) {
        if (dto == null)
            return;

        //成人成本价
        BigDecimal adultCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_ADULT);
        //小童成本价
        BigDecimal childrenCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_CHILD);
        //长者成本价
        BigDecimal oldCostPrice = costPriceMap.get(BusConst.TOURIST_TYPE_OLD);

        dto.setAdultPrice(adultCostPrice);
        dto.setChildrenPrice(childrenCostPrice);



        //加幅价格
        if (increaseStrategyRule != null) {
            dto.setAdultPrice(addePrice(increaseStrategyRule, adultCostPrice, dto.getAdultPrice()));
            dto.setChildrenPrice(addePrice(increaseStrategyRule, childrenCostPrice, dto.getChildrenPrice()));
        }
    }


    /**
     * 价格加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addePrice(TrainProductIncreaseStrategyRule rule, BigDecimal costPrice, BigDecimal price) {
        if (price == null)
            return null;
        return price.add(addePrice(rule, costPrice));
    }

    /**
     * 价格加幅设置
     *
     * @param rule
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addePrice(TrainProductIncreaseStrategyRule rule, BigDecimal costPrice) {
        if (rule == null)
            return BigDecimal.ZERO;
        return addePrice(rule.getPriceType(), rule.getPrice(), costPrice);
    }

    /**
     * 价格加幅设置
     *
     * @param rulePriceType 加幅价格类型，1：数值加幅；2：百分比加幅；
     * @param rulePrice     加幅值
     * @param costPrice 成本价
     * @return 加幅的值
     */
    private BigDecimal addePrice(Integer rulePriceType, BigDecimal rulePrice, BigDecimal costPrice) {
        if (rulePriceType == null || rulePrice == null || costPrice == null) return BigDecimal.ZERO;

        //数值加幅
        if (BConst.ONE.equals(rulePriceType)) {
            return rulePrice;
        } else if (BConst.TWO.equals(rulePriceType)) {  //百分比加幅
            return Assist.calcPercent(costPrice, rulePrice);
        }

        return BigDecimal.ZERO;
    }

    /**
     * 根据部门信息，递归查询加幅策略-线下自营信息
     *
     * @param sysDepartmentDTO   部门信息
     * @param increaseStrategyId 加幅策略id
     * @return 加幅策略-线下自营信息
     */
    private TrainProductChannelOfflineSelfCustom findParentDepartmentId(SysDepartmentDTO sysDepartmentDTO, Long increaseStrategyId) {
        QueryWrapper<TrainProductChannelOfflineSelfCustom> offlineSelfQueryWrapper = new QueryWrapper<>();
        offlineSelfQueryWrapper.eq("relation_id", sysDepartmentDTO.getId());
        offlineSelfQueryWrapper.lambda().eq(TrainProductChannelOfflineSelfCustom::getIncreaseStrategyId, increaseStrategyId);
        TrainProductChannelOfflineSelfCustom busProductChannelOfflineSelfCustom = trainProductChannelOfflineSelfCustomMapper.selectOne(offlineSelfQueryWrapper);
        if (busProductChannelOfflineSelfCustom == null && sysDepartmentDTO.getParentId() != null) {
            // 查找上級部門
            SysDepartmentDTO sysDepartmentDTOTemp = sysDepartmentService.queryOne(sysDepartmentDTO.getParentId());
            if (sysDepartmentDTOTemp == null) {
                return null; //没有上级部门，返回null
            }
            busProductChannelOfflineSelfCustom = findParentDepartmentId(sysDepartmentDTOTemp, increaseStrategyId);

        }
        return busProductChannelOfflineSelfCustom;
    }


    /**
     * 推荐价格加幅设置
     * @param recommendedTrainDTO
     * @param priceType
     * @param productPrice
     */
    private void buildIncreasePrice(RecommendedTrainDTO recommendedTrainDTO, Integer priceType, BigDecimal productPrice) {

        // 单程票-成人票数值加幅
        if (priceType != null && priceType == 1) {
            if(productPrice!=null){
                BigDecimal adultOneWayPrice = recommendedTrainDTO.getPrice().add(productPrice);
                recommendedTrainDTO.setPrice(adultOneWayPrice);
            }

        }
        // 单程票-成人票百分比加幅
        if (priceType != null && priceType == 2) {
            if(productPrice!=null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                BigDecimal addPrice = recommendedTrainDTO.getPrice().add(recommendedTrainDTO.getPrice().multiply(per));
                recommendedTrainDTO.setPrice(addPrice);
            }
        }
    }


    /**
     * 成人票价格加幅设置
     * @param reservationTrainPageDTO
     * @param priceType
     * @param productPrice
     */
    private void addeAdultPrice(ReservationTrainPageDTO reservationTrainPageDTO, Integer priceType, BigDecimal productPrice) {
        // 单程票-成人儿童票数值加幅
        if (priceType != null && priceType == 1) {
            if(productPrice!=null){
                if(reservationTrainPageDTO.getAdultPrice() != null) {
                    BigDecimal adultOneWayPrice = reservationTrainPageDTO.getAdultPrice().add(productPrice);
                    reservationTrainPageDTO.setAdultPrice(adultOneWayPrice);
                }
            }
        }

        // 单程票-成人儿童票百分比加幅
        if (priceType != null && priceType == 2) {
            if(productPrice!=null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                if(reservationTrainPageDTO.getAdultPrice() != null){
                    BigDecimal adultPrice = reservationTrainPageDTO.getAdultPrice().add(reservationTrainPageDTO.getAdultPrice().multiply(per));
                    reservationTrainPageDTO.setAdultPrice(adultPrice);
                }
            }
        }
    }


    /**
     * 儿童票价格加幅设置
     * @param reservationTrainPageDTO
     * @param priceType
     * @param productPrice
     */
    private void addeChildRenPrice(ReservationTrainPageDTO reservationTrainPageDTO, Integer priceType, BigDecimal productPrice) {
        // 单程票-儿童票数值加幅
        if (priceType != null && priceType == 1) {
            if(productPrice!=null){
                if(reservationTrainPageDTO.getChildrenPrice() != null){
                    BigDecimal chilRenOneWayPrice = reservationTrainPageDTO.getChildrenPrice().add(productPrice);
                    reservationTrainPageDTO.setChildrenPrice(chilRenOneWayPrice);
                }
            }
        }

        // 单程票-成人儿童票百分比加幅
        if (priceType != null && priceType == 2) {
            if(productPrice!=null) {
                BigDecimal per = productPrice.divide(new BigDecimal("100"));
                if(reservationTrainPageDTO.getChildrenPrice() != null){
                    BigDecimal childRenPrice = reservationTrainPageDTO.getChildrenPrice().add(reservationTrainPageDTO.getChildrenPrice().multiply(per));
                    reservationTrainPageDTO.setChildrenPrice(childRenPrice);
                }
            }
        }
    }


    /**
     * 私有方法-新增火车票产品
     * @param trainProductReq
     */
    private Result addProductInfo(TrainProductReq trainProductReq,TokenUser user){
        // 返回上一步再保存需带id
        if (trainProductReq.getId() != null) {
            // 删除旧数据
            trainProductMapper.deleteById(trainProductReq.getId());
            List<TrainProductCost> costList = trainProductCostMapper.selectList(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId,
                    trainProductReq.getId()));
            trainProductCostMapper.delete(new QueryWrapper<TrainProductCost>().lambda().eq(TrainProductCost::getTrainProductId,
                    trainProductReq.getId()));
            List<Long> costIdList = costList.stream().map(TrainProductCost::getId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(costIdList)) {
                trainProductCostDateMapper.delete(new QueryWrapper<TrainProductCostDate>().lambda().in(TrainProductCostDate::getCostId,
                        costIdList));
                trainProducCostPriceMapper.delete(new QueryWrapper<TrainProducCostPrice>().lambda().in(TrainProducCostPrice::getCostId,
                        costIdList));
            }
        }

        //保存火车票产品信息
        TrainProduct trainProduct = EntityUtil.copy(trainProductReq, TrainProduct.class);
        Long trainProductId = SnowflakeIdWorker.nextId();
        trainProduct.setProductCode(buildOrderNumber(user.getId(), LocalDateTime.now()));
        trainProduct.setId(trainProductId);
        //如果页面没有填写负责人,则默认当前账号
        if(StringUtils.isEmpty(trainProductReq.getChargePersonId())){
            trainProduct.setChargePersonId(user.getId());
            trainProduct.setChargePersonName(user.getUsername());
        }
        trainProduct.setCreateId(user.getId());
        trainProduct.setGmtCreate(LocalDateTime.now());
        trainProduct.setIsDeleted(IsDeletedCode.NO.getCode());
        trainProduct.setApprovalStatus(ApproveCode.UN_COMMIT.getCode());
        trainProduct.setSaleStatus(IsValidCode.IN_VALID.getCode());
        trainProduct.setProductSource(ProductType.MANUAL_ENTRY.getCode());
        trainProduct.setOnShelfStatus(Constants.NO_ONSHELF);
        trainProductMapper.insert(trainProduct);


        //保存火车票产品成本信息
        List<TrainProductCostReq> trainProductCostReqList = trainProductReq.getTrainProductCostReqList();
        for(TrainProductCostReq trainProductCostReq : trainProductCostReqList){

            //保存火车票产品成本
            TrainProductCost trainProductCost = EntityUtil.copy(trainProductCostReq, TrainProductCost.class);
            Long costId = SnowflakeIdWorker.nextId();
            trainProductCost.setId(costId);
            trainProductCost.setTrainProductId(trainProductId);
            trainProductCostMapper.insert(trainProductCost);

            //保存火车票产品成本日期
            List<TrainProductCostDateReq> trainProductCostDateReqList = trainProductCostReq.getTrainProductCostDateReqList();
            for(TrainProductCostDateReq trainProductCostDateReq : trainProductCostDateReqList){
                TrainProductCostDate trainProductCostDate = EntityUtil.copy(trainProductCostDateReq, TrainProductCostDate.class);
                trainProductCostDate.setId(SnowflakeIdWorker.nextId());
                trainProductCostDate.setCostId(costId);
                trainProductCostDateMapper.insert(trainProductCostDate);
            }
            //保存火车票产品成本价格
            List<TrainProducCostPriceReq> trainProducCostPriceReqList = trainProductCostReq.getTrainProducCostPriceReqList();
            for(TrainProducCostPriceReq trainProducCostPriceReq : trainProducCostPriceReqList){
                TrainProducCostPrice trainProducCostPrice = EntityUtil.copy(trainProducCostPriceReq, TrainProducCostPrice.class);
                trainProducCostPrice.setAlightingStationId(trainProductReq.getAlightingStationId());
                trainProducCostPrice.setAlightingStationName(trainProductReq.getAlightingStationName());
                trainProducCostPrice.setBoardingStationId(trainProductReq.getBoardingStationId());
                trainProducCostPrice.setBoardingStationName(trainProductReq.getBoardingStationName());
                trainProducCostPrice.setId(SnowflakeIdWorker.nextId());
                trainProducCostPrice.setCostId(costId);
                trainProducCostPriceMapper.insert(trainProducCostPrice);
            }
        }
        return Result.success(trainProductId);
    }


    /**
     * 计算可售数量 = 总库存数 - 已售数量
     *
     * @param trainProductIncreaseStrategyRule
     */
    private int buildRemainderNumber(TrainProductIncreaseStrategyRule trainProductIncreaseStrategyRule) {
        // 火车产品成本每日库存
        int stock = trainProductIncreaseStrategyRule.getStock();
        if (Constants.SALE_TYPE_LIMIT.equals(trainProductIncreaseStrategyRule.getSaleableType())) {
            int saleableNumber = trainProductIncreaseStrategyRule.getSaleableNumber() == null ? 0 : Math.min(stock,trainProductIncreaseStrategyRule.getSaleableNumber());
            int soldNumber = trainProductIncreaseStrategyRule.getSoldNumber() == null ? 0 : trainProductIncreaseStrategyRule.getSoldNumber();
            return saleableNumber - soldNumber;
        } else if (Constants.SALE_TYPE_UNLIMITED.equals(trainProductIncreaseStrategyRule.getSaleableType())) {
            int soldNumber = trainProductIncreaseStrategyRule.getSoldNumber() == null ? 0 : trainProductIncreaseStrategyRule.getSoldNumber();
            if(stock > soldNumber) {
                return stock - soldNumber;
            }
        }
        return 0;
    }


    /**
     * 校验产品信息入参
     * @param trainProductReq
     * @param user
     * @return
     */
    private Result checkProductReq(TrainProductReq trainProductReq, TokenUser user){
        if(Objects.isNull(user)){
            return Result.failed(SystemError.USER_1000);
        }
        if(Objects.isNull(trainProductReq)){
            return Result.failed(SystemError.TRAIN_PRODUCT_14002);
        }
        return null;
    }


    /**
     * 产品成本日期校验
     * @param trainProductCostReqList
     * @return
     */
    private Result<Object> checkCostateResult(List<TrainProductCostReq> trainProductCostReqList) {
        List<TrainProductCostDateReq> costDateReqList = new ArrayList<>();
        for (TrainProductCostReq req : trainProductCostReqList) {
            costDateReqList.addAll(req.getTrainProductCostDateReqList());
        }
        for (int i = 0; i < costDateReqList.size(); i++) {
            TrainProductCostDateReq productCostDateReq = costDateReqList.get(i);
            if (productCostDateReq.getDateBegin().isBefore(LocalDate.now())) {
                // 火车票产品加幅策略保存，开始日期不能小于当前日期校验
                return Result.failed(SystemError.BUS_PRODUCT_9024);
            }
            if (i == 0 && productCostDateReq.getDateBegin().isAfter(productCostDateReq.getDateEnd())) {
                // 开始日期必须小于结束日期校验
                return Result.failed(SystemError.BUS_PRODUCT_9021);
            }
            for (int j = 0; j < costDateReqList.size(); j++) {
                TrainProductCostDateReq costDateReqTemp = costDateReqList.get(j);
                if (i >= j) { // 自身和已经校验过的跳过日期校验
                    continue;
                }
                if (i == 0 && costDateReqTemp.getDateBegin().isAfter(costDateReqTemp.getDateEnd())) {
                    // 开始日期必须小于结束日期校验
                    return Result.failed(SystemError.BUS_PRODUCT_9021);
                }
                if (DateUtil.match(productCostDateReq.getDateBegin(), productCostDateReq.getDateEnd(), costDateReqTemp.getDateBegin(), costDateReqTemp.getDateEnd())) {
                    // 当前日期与其他日期区域重叠校验
                    return Result.failed(SystemError.BUS_PRODUCT_9022);
                }
            }
        }
        return null;
    }


    /**
     * 生成火车票产品编码=PG+员工编号+月日4位+时分4位+3位随机数字
     *
     * @param userId
     * @return
     */
    private String buildOrderNumber(Long userId, LocalDateTime nowLocalDateTime) {
        UserDTO userDTO = sysUserService.loadUserByParam(userId, 1);
        String employeeNumber = userDTO.getEmployeeNumber();
        String monthCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getMonthValue()), 2, "0");
        String dayCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getDayOfMonth()), 2, "0");
        String hourCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getHour()), 2, "0");
        String minuteCode = org.apache.commons.lang3.StringUtils.leftPad(String.valueOf(nowLocalDateTime.getMinute()), 2, "0");
        String randomNumber = String.valueOf((int) ((Math.random() * 9 + 1) * 100));
        StringBuilder orderNumberSb = new StringBuilder();
        orderNumberSb.append("PG").append(employeeNumber).append(monthCode).append(dayCode).append(hourCode).append(minuteCode).append(randomNumber);
        return orderNumberSb.toString();
    }


}
